diff --git a/gas/ChangeLog b/gas/ChangeLog index 2b1d99c94d1..9bc4a157b0a 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,16 @@ +2015-05-15 H.J. Lu + + * config/tc-i386.c (shared): New. + (OPTION_MSHARED): Likewise. + (elf_symbol_resolved_in_segment_p): Add relocation argument. + Check PLT relocations and shared. + (md_estimate_size_before_relax): Pass fragP->fr_var to + elf_symbol_resolved_in_segment_p. + (md_longopts): Add -mshared. + (md_show_usage): Likewise. + (md_parse_option): Handle OPTION_MSHARED. + * doc/c-i386.texi: Document -mshared. + 2015-05-14 H.J. Lu * write.c (compress_debug): Don't write the zlib header, which diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c index 75f268f92f0..254548f2101 100644 --- a/gas/config/tc-i386.c +++ b/gas/config/tc-i386.c @@ -524,6 +524,11 @@ static enum x86_elf_abi x86_elf_abi = I386_ABI; static int use_big_obj = 0; #endif +#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) +/* 1 if generating code for a shared library. */ +static int shared = 0; +#endif + /* 1 for intel syntax, 0 if att syntax. */ static int intel_syntax = 0; @@ -8818,7 +8823,7 @@ i386_frag_max_var (fragS *frag) #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) static int -elf_symbol_resolved_in_segment_p (symbolS *fr_symbol) +elf_symbol_resolved_in_segment_p (symbolS *fr_symbol, offsetT fr_var) { /* STT_GNU_IFUNC symbol must go through PLT. */ if ((symbol_get_bfdsym (fr_symbol)->flags @@ -8829,9 +8834,24 @@ elf_symbol_resolved_in_segment_p (symbolS *fr_symbol) /* Symbol may be weak or local. */ return !S_IS_WEAK (fr_symbol); + /* Global symbols with non-default visibility can't be preempted. */ + if (ELF_ST_VISIBILITY (S_GET_OTHER (fr_symbol)) != STV_DEFAULT) + return 1; + + if (fr_var != NO_RELOC) + switch ((enum bfd_reloc_code_real) fr_var) + { + case BFD_RELOC_386_PLT32: + case BFD_RELOC_X86_64_PLT32: + /* Symbol with PLT relocatin may be preempted. */ + return 0; + default: + abort (); + } + /* Global symbols with default visibility in a shared library may be preempted by another definition. */ - return ELF_ST_VISIBILITY (S_GET_OTHER (fr_symbol)) != STV_DEFAULT; + return !shared; } #endif @@ -8858,7 +8878,8 @@ md_estimate_size_before_relax (fragS *fragP, segT segment) if (S_GET_SEGMENT (fragP->fr_symbol) != segment #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) || (IS_ELF - && !elf_symbol_resolved_in_segment_p (fragP->fr_symbol)) + && !elf_symbol_resolved_in_segment_p (fragP->fr_symbol, + fragP->fr_var)) #endif #if defined (OBJ_COFF) && defined (TE_PE) || (OUTPUT_FLAVOR == bfd_target_coff_flavour @@ -9528,6 +9549,7 @@ const char *md_shortopts = "qn"; #define OPTION_MBIG_OBJ (OPTION_MD_BASE + 18) #define OPTION_OMIT_LOCK_PREFIX (OPTION_MD_BASE + 19) #define OPTION_MEVEXRCIG (OPTION_MD_BASE + 20) +#define OPTION_MSHARED (OPTION_MD_BASE + 21) struct option md_longopts[] = { @@ -9538,6 +9560,7 @@ struct option md_longopts[] = #endif #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) {"x32", no_argument, NULL, OPTION_X32}, + {"mshared", no_argument, NULL, OPTION_MSHARED}, #endif {"divide", no_argument, NULL, OPTION_DIVIDE}, {"march", required_argument, NULL, OPTION_MARCH}, @@ -9598,6 +9621,10 @@ md_parse_option (int c, char *arg) /* -s: On i386 Solaris, this tells the native assembler to use .stab instead of .stab.excl. We always use .stab anyhow. */ break; + + case OPTION_MSHARED: + shared = 1; + break; #endif #if (defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF) \ || defined (TE_PE) || defined (TE_PEP) || defined (OBJ_MACH_O)) @@ -10027,6 +10054,8 @@ md_show_usage (FILE *stream) -mold-gcc support old (<= 2.8.1) versions of gcc\n")); fprintf (stream, _("\ -madd-bnd-prefix add BND prefix for all valid branches\n")); + fprintf (stream, _("\ + -mshared disable branch optimization for shared code\n")); # if defined (TE_PE) || defined (TE_PEP) fprintf (stream, _("\ -mbig-obj generate big object files\n")); diff --git a/gas/doc/c-i386.texi b/gas/doc/c-i386.texi index 1645c8cba36..ea08c632fe8 100644 --- a/gas/doc/c-i386.texi +++ b/gas/doc/c-i386.texi @@ -298,6 +298,17 @@ The @code{.att_syntax} and @code{.intel_syntax} directives will take precedent. This option forces the assembler to add BND prefix to all branches, even if such prefix was not explicitly specified in the source code. +@cindex @samp{-mshared} option, i386 +@cindex @samp{-mshared} option, x86-64 +@item -mno-shared +On ELF target, the assembler normally optimizes out non-PLT relocations +against defined non-weak global branch targets with default visibility. +The @samp{-mshared} option tells the assembler to generate code which +may go into a shared library where all non-weak global branch targets +with default visibility can be preempted. The resulting code is +slightly bigger. This option only affects the handling of branch +instructions. + @cindex @samp{-mbig-obj} option, x86-64 @item -mbig-obj On x86-64 PE/COFF target this option forces the use of big object file diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index dab5fcf50a3..95b75837266 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2015-05-15 H.J. Lu + + * gas/i386/i386.exp: Don't run pcrel for ELF targets. Run + pcrel-elf, relax-4 and x86-64-relax-3 for ELF targets. + * gas/i386/pcrel-elf.d: New file. + * gas/i386/relax-4.d: Likewise. + * gas/i386/x86-64-relax-3.d: Likewise. + * gas/i386/relax-3.d: Pass -mshared to assembler. Updated. + * gas/i386/x86-64-relax-2.d: Likewise. + * gas/i386/relax-3.s: Add test for PLT relocation. + 2015-05-14 Peter Bergner * gas/ppc/power4.d: Add a slbia test. diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp index b6f28107460..ff648b04cf4 100644 --- a/gas/testsuite/gas/i386/i386.exp +++ b/gas/testsuite/gas/i386/i386.exp @@ -352,8 +352,10 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_32_check]] # but the relocs we currently produce are slightly different # from those produced for ELF/COFF based toolchains. # So for now we ignore PE targets. - run_dump_test "pcrel" run_dump_test "absrel" + if {[istarget "*-*-coff*"]} then { + run_dump_test "pcrel" + } } # ELF specific tests @@ -361,6 +363,7 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_32_check]] # PIC is only supported on ELF targets. run_dump_test "intelpic" + run_dump_test "pcrel-elf" run_dump_test "relax" run_dump_test "gotpc" run_dump_test "tlsd" @@ -396,6 +399,7 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_32_check]] run_dump_test "note" run_dump_test "relax-3" + run_dump_test "relax-4" if {![istarget "*-*-nacl*"]} then { run_dump_test "iamcu-1" @@ -763,6 +767,7 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_64_check]] t run_list_test "x86-64-size-inval-1" "-al" run_dump_test "x86-64-relax-2" + run_dump_test "x86-64-relax-3" run_dump_test "x86-64-jump" } diff --git a/gas/testsuite/gas/i386/pcrel-elf.d b/gas/testsuite/gas/i386/pcrel-elf.d new file mode 100644 index 00000000000..e4d45c87c5f --- /dev/null +++ b/gas/testsuite/gas/i386/pcrel-elf.d @@ -0,0 +1,52 @@ +#source: pcrel.s +#as: -mshared +#objdump: -drw +#name: i386 pcrel ELF reloc + +.*: +file format .*i386.* + +Disassembly of section \.text: + +0+ : +[ ]*[a-f0-9]+: e9 30 12 00 00 jmp 1235 1: R_386_PC32 \*ABS\* + +0+5 : +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 6 6: R_386_PC32 ext +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp b b: R_386_PC32 weak +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 10 10: R_386_PC32 comm +[ ]*[a-f0-9]+: eb ea jmp 0 +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 17 17: R_386_PC32 glob +[ ]*[a-f0-9]+: e9 72 98 00 00 jmp 9892 1c: R_386_PC32 \*ABS\* +[ ]*[a-f0-9]+: e9 db 00 00 00 jmp 100 +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 26 26: R_386_PC32 glob2 +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 2b 2b: R_386_PC32 .data +[ ]*[a-f0-9]+: e9 00 00 00 00 jmp 34 30: R_386_PC32 .data +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 35 35: R_386_PC32 \*ABS\* +[ ]*[a-f0-9]+: e9 c8 ed ff ff jmp ffffee06 3a: R_386_PC32 ext +[ ]*[a-f0-9]+: e9 c8 ed ff ff jmp ffffee0b 3f: R_386_PC32 weak +[ ]*[a-f0-9]+: e9 c8 ed ff ff jmp ffffee10 44: R_386_PC32 comm +[ ]*[a-f0-9]+: e9 7f ed ff ff jmp ffffedcc +[ ]*[a-f0-9]+: e9 c8 ed ff ff jmp ffffee1a 4e: R_386_PC32 glob +[ ]*[a-f0-9]+: e9 3e 86 00 00 jmp 8695 53: R_386_PC32 \*ABS\* +[ ]*[a-f0-9]+: e9 70 ee ff ff jmp ffffeecc +[ ]*[a-f0-9]+: e9 c8 ed ff ff jmp ffffee29 5d: R_386_PC32 glob2 +[ ]*[a-f0-9]+: e9 c8 ed ff ff jmp ffffee2e 62: R_386_PC32 .data +[ ]*[a-f0-9]+: e9 cc ed ff ff jmp ffffee37 67: R_386_PC32 .data +[ ]*[a-f0-9]+: e9 ba 79 ff ff jmp ffff7a2a 6c: R_386_PC32 \*ABS\* +[ ]*[a-f0-9]+: e9 86 67 ff ff jmp ffff67fb 71: R_386_PC32 ext +[ ]*[a-f0-9]+: e9 86 67 ff ff jmp ffff6800 76: R_386_PC32 weak +[ ]*[a-f0-9]+: e9 86 67 ff ff jmp ffff6805 7b: R_386_PC32 comm +[ ]*[a-f0-9]+: e9 06 67 ff ff jmp ffff678a +[ ]*[a-f0-9]+: e9 06 67 ff ff jmp ffff678f +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 8a 8a: R_386_PC32 \*ABS\* +[ ]*[a-f0-9]+: e9 f7 67 ff ff jmp ffff688a +[ ]*[a-f0-9]+: e9 f7 67 ff ff jmp ffff688f +[ ]*[a-f0-9]+: e9 86 67 ff ff jmp ffff6823 99: R_386_PC32 .data +[ ]*[a-f0-9]+: e9 8a 67 ff ff jmp ffff682c 9e: R_386_PC32 .data +[ ]*[a-f0-9]+: e9 fc 00 00 00 jmp 1a3 a3: R_386_PC32 \*ABS\* +[ ]*[a-f0-9]+: e9 01 00 00 00 jmp ad a8: R_386_PC32 \*ABS\* +[ ]*[a-f0-9]+: e9 01 ff ff ff jmp ffffffb2 ad: R_386_PC32 \*ABS\* +[ ]*[a-f0-9]+: e9 01 01 00 00 jmp 1b7 b2: R_386_PC32 \*ABS\* +[ ]*[a-f0-9]+: e9 01 00 00 00 jmp bc b7: R_386_PC32 \*ABS\* + ... +#pass diff --git a/gas/testsuite/gas/i386/relax-3.d b/gas/testsuite/gas/i386/relax-3.d index 8aa94e97fec..4610553e51a 100644 --- a/gas/testsuite/gas/i386/relax-3.d +++ b/gas/testsuite/gas/i386/relax-3.d @@ -1,3 +1,4 @@ +#as: -mshared #objdump: -dwr .*: +file format .* @@ -5,26 +6,27 @@ Disassembly of section .text: 0+ : -[ ]*[a-f0-9]+: eb 1f jmp 21 -[ ]*[a-f0-9]+: eb 19 jmp 1d -[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 5 5: (R_386_PC)?(DISP)?32 global_def -[ ]*[a-f0-9]+: e9 fc ff ff ff jmp a a: (R_386_PC)?(DISP)?32 weak_def -[ ]*[a-f0-9]+: e9 fc ff ff ff jmp f f: (R_386_PC)?(DISP)?32 weak_hidden_undef -[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 14 14: (R_386_PC)?(DISP)?32 weak_hidden_def -[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 19 19: (R_386_PC)?(DISP)?32 hidden_undef +[ ]*[a-f0-9]+: eb 24 jmp 26 +[ ]*[a-f0-9]+: eb 1e jmp 22 +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 5 5: R_386_PC32 global_def +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp a a: R_386_PLT32 global_def +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp f f: R_386_PC32 weak_def +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 14 14: R_386_PC32 weak_hidden_undef +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 19 19: R_386_PC32 weak_hidden_def +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 1e 1e: R_386_PC32 hidden_undef -0+1d : +0+22 : [ ]*[a-f0-9]+: c3 ret -0+1e : +0+23 : [ ]*[a-f0-9]+: c3 ret -0+1f : +0+24 : [ ]*[a-f0-9]+: c3 ret -0+20 : +0+25 : [ ]*[a-f0-9]+: c3 ret -0+21 : +0+26 : [ ]*[a-f0-9]+: c3 ret #pass diff --git a/gas/testsuite/gas/i386/relax-3.s b/gas/testsuite/gas/i386/relax-3.s index ab521854f0b..48ea917df5f 100644 --- a/gas/testsuite/gas/i386/relax-3.s +++ b/gas/testsuite/gas/i386/relax-3.s @@ -4,6 +4,7 @@ foo: jmp local jmp hidden_def jmp global_def + jmp global_def@PLT jmp weak_def jmp weak_hidden_undef jmp weak_hidden_def diff --git a/gas/testsuite/gas/i386/relax-4.d b/gas/testsuite/gas/i386/relax-4.d new file mode 100644 index 00000000000..20392512252 --- /dev/null +++ b/gas/testsuite/gas/i386/relax-4.d @@ -0,0 +1,32 @@ +#source: relax-3.s +#objdump: -dwr + +.*: +file format .* + +Disassembly of section .text: + +0+ : +[ ]*[a-f0-9]+: eb 21 jmp 23 +[ ]*[a-f0-9]+: eb 1b jmp 1f +[ ]*[a-f0-9]+: eb 1b jmp 21 +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 7 7: R_386_PLT32 global_def +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp c c: R_386_PC32 weak_def +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 11 11: R_386_PC32 weak_hidden_undef +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 16 16: R_386_PC32 weak_hidden_def +[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 1b 1b: R_386_PC32 hidden_undef + +0+1f : +[ ]*[a-f0-9]+: c3 ret + +0+20 : +[ ]*[a-f0-9]+: c3 ret + +0+21 : +[ ]*[a-f0-9]+: c3 ret + +0+22 : +[ ]*[a-f0-9]+: c3 ret + +0+23 : +[ ]*[a-f0-9]+: c3 ret +#pass diff --git a/gas/testsuite/gas/i386/x86-64-relax-2.d b/gas/testsuite/gas/i386/x86-64-relax-2.d index 7b0bd567b6a..c124102982d 100644 --- a/gas/testsuite/gas/i386/x86-64-relax-2.d +++ b/gas/testsuite/gas/i386/x86-64-relax-2.d @@ -1,4 +1,5 @@ #source: relax-3.s +#as: -mshared #objdump: -dwr .*: +file format .* @@ -7,26 +8,27 @@ Disassembly of section .text: 0+ : -[ ]*[a-f0-9]+: eb 1f jmp 21 -[ ]*[a-f0-9]+: eb 19 jmp 1d +[ ]*[a-f0-9]+: eb 24 jmp 26 +[ ]*[a-f0-9]+: eb 1e jmp 22 [ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 9 5: R_X86_64_PC32 global_def-0x4 -[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq e a: R_X86_64_PC32 weak_def-0x4 -[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 13 f: R_X86_64_PC32 weak_hidden_undef-0x4 -[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 18 14: R_X86_64_PC32 weak_hidden_def-0x4 -[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 1d 19: R_X86_64_PC32 hidden_undef-0x4 +[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq e a: R_X86_64_PLT32 global_def-0x4 +[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 13 f: R_X86_64_PC32 weak_def-0x4 +[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 18 14: R_X86_64_PC32 weak_hidden_undef-0x4 +[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 1d 19: R_X86_64_PC32 weak_hidden_def-0x4 +[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 22 1e: R_X86_64_PC32 hidden_undef-0x4 -0+1d : +0+22 : [ ]*[a-f0-9]+: c3 retq -0+1e : +0+23 : [ ]*[a-f0-9]+: c3 retq -0+1f : +0+24 : [ ]*[a-f0-9]+: c3 retq -0+20 : +0+25 : [ ]*[a-f0-9]+: c3 retq -0+21 : +0+26 : [ ]*[a-f0-9]+: c3 retq #pass diff --git a/gas/testsuite/gas/i386/x86-64-relax-3.d b/gas/testsuite/gas/i386/x86-64-relax-3.d new file mode 100644 index 00000000000..98fd28dd11e --- /dev/null +++ b/gas/testsuite/gas/i386/x86-64-relax-3.d @@ -0,0 +1,33 @@ +#source: relax-3.s +#objdump: -dwr + +.*: +file format .* + + +Disassembly of section .text: + +0+ : +[ ]*[a-f0-9]+: eb 21 jmp 23 +[ ]*[a-f0-9]+: eb 1b jmp 1f +[ ]*[a-f0-9]+: eb 1b jmp 21 +[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq b 7: R_X86_64_PLT32 global_def-0x4 +[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 10 c: R_X86_64_PC32 weak_def-0x4 +[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 15 11: R_X86_64_PC32 weak_hidden_undef-0x4 +[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 1a 16: R_X86_64_PC32 weak_hidden_def-0x4 +[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 1f 1b: R_X86_64_PC32 hidden_undef-0x4 + +0+1f : +[ ]*[a-f0-9]+: c3 retq + +0+20 : +[ ]*[a-f0-9]+: c3 retq + +0+21 : +[ ]*[a-f0-9]+: c3 retq + +0+22 : +[ ]*[a-f0-9]+: c3 retq + +0+23 : +[ ]*[a-f0-9]+: c3 retq +#pass