From: H.J. Lu Date: Fri, 15 May 2015 10:17:31 +0000 (-0700) Subject: Add -mshared option to x86 ELF assembler X-Git-Tag: gdb-7.10-release~497 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8dcea93252a9ea7dff57e85220a719e2a5e8ab41;p=external%2Fbinutils.git Add -mshared option to x86 ELF assembler This patch adds -mshared option to x86 ELF assembler. By default, assembler will optimize out non-PLT relocations against defined non-weak global branch targets with default visibility. The -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. This Linux kernel patch is needed to create a working x86 Linux kernel if it hasn't been applied: diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S index ae6588b..b91a00c 100644 --- a/arch/x86/kernel/head_64.S +++ b/arch/x86/kernel/head_64.S @@ -339,8 +339,8 @@ early_idt_handlers: i = i + 1 .endr -/* This is global to keep gas from relaxing the jumps */ -ENTRY(early_idt_handler) +/* This is weak to keep gas from relaxing the jumps */ +WEAK(early_idt_handler) cld cmpl $2,(%rsp) # X86_TRAP_NMI -- gas/ * 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. gas/testsuite/ * 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. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index 2b1d99c..9bc4a15 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 75f268f..254548f 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 1645c8c..ea08c63 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 dab5fcf..95b7583 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 b6f2810..ff648b0 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 0000000..e4d45c8 --- /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 8aa94e9..4610553 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 - -0+1d : +[ ]*[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+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 ab52185..48ea917 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 0000000..2039251 --- /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 7b0bd56..c124102 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 0000000..98fd28d --- /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