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.
+2015-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ * 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 <hongjiu.lu@intel.com>
* write.c (compress_debug): Don't write the zlib header, which
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;
#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
/* 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
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
#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[] =
{
#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},
/* -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))
-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"));
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
+2015-05-15 H.J. Lu <hongjiu.lu@intel.com>
+
+ * 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 <bergner@vnet.ibm.com>
* gas/ppc/power4.d: Add a slbia test.
# 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
# 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"
run_dump_test "note"
run_dump_test "relax-3"
+ run_dump_test "relax-4"
if {![istarget "*-*-nacl*"]} then {
run_dump_test "iamcu-1"
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"
}
--- /dev/null
+#source: pcrel.s
+#as: -mshared
+#objdump: -drw
+#name: i386 pcrel ELF reloc
+
+.*: +file format .*i386.*
+
+Disassembly of section \.text:
+
+0+ <loc>:
+[ ]*[a-f0-9]+: e9 30 12 00 00 jmp 1235 <abs\+0x1> 1: R_386_PC32 \*ABS\*
+
+0+5 <glob>:
+[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 6 <glob\+0x1> 6: R_386_PC32 ext
+[ ]*[a-f0-9]+: e9 fc ff ff ff jmp b <glob\+0x6> b: R_386_PC32 weak
+[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 10 <glob\+0xb> 10: R_386_PC32 comm
+[ ]*[a-f0-9]+: eb ea jmp 0 <loc>
+[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 17 <glob\+0x12> 17: R_386_PC32 glob
+[ ]*[a-f0-9]+: e9 72 98 00 00 jmp 9892 <abs2\+0x1c> 1c: R_386_PC32 \*ABS\*
+[ ]*[a-f0-9]+: e9 db 00 00 00 jmp 100 <loc2>
+[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 26 <glob\+0x21> 26: R_386_PC32 glob2
+[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 2b <glob\+0x26> 2b: R_386_PC32 .data
+[ ]*[a-f0-9]+: e9 00 00 00 00 jmp 34 <glob\+0x2f> 30: R_386_PC32 .data
+[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 35 <glob\+0x30> 35: R_386_PC32 \*ABS\*
+[ ]*[a-f0-9]+: e9 c8 ed ff ff jmp ffffee06 <abs2\+0xffff5590> 3a: R_386_PC32 ext
+[ ]*[a-f0-9]+: e9 c8 ed ff ff jmp ffffee0b <abs2\+0xffff5595> 3f: R_386_PC32 weak
+[ ]*[a-f0-9]+: e9 c8 ed ff ff jmp ffffee10 <abs2\+0xffff559a> 44: R_386_PC32 comm
+[ ]*[a-f0-9]+: e9 7f ed ff ff jmp ffffedcc <abs2\+0xffff5556>
+[ ]*[a-f0-9]+: e9 c8 ed ff ff jmp ffffee1a <abs2\+0xffff55a4> 4e: R_386_PC32 glob
+[ ]*[a-f0-9]+: e9 3e 86 00 00 jmp 8695 <abs\+0x7461> 53: R_386_PC32 \*ABS\*
+[ ]*[a-f0-9]+: e9 70 ee ff ff jmp ffffeecc <abs2\+0xffff5656>
+[ ]*[a-f0-9]+: e9 c8 ed ff ff jmp ffffee29 <abs2\+0xffff55b3> 5d: R_386_PC32 glob2
+[ ]*[a-f0-9]+: e9 c8 ed ff ff jmp ffffee2e <abs2\+0xffff55b8> 62: R_386_PC32 .data
+[ ]*[a-f0-9]+: e9 cc ed ff ff jmp ffffee37 <abs2\+0xffff55c1> 67: R_386_PC32 .data
+[ ]*[a-f0-9]+: e9 ba 79 ff ff jmp ffff7a2a <abs2\+0xfffee1b4> 6c: R_386_PC32 \*ABS\*
+[ ]*[a-f0-9]+: e9 86 67 ff ff jmp ffff67fb <abs2\+0xfffecf85> 71: R_386_PC32 ext
+[ ]*[a-f0-9]+: e9 86 67 ff ff jmp ffff6800 <abs2\+0xfffecf8a> 76: R_386_PC32 weak
+[ ]*[a-f0-9]+: e9 86 67 ff ff jmp ffff6805 <abs2\+0xfffecf8f> 7b: R_386_PC32 comm
+[ ]*[a-f0-9]+: e9 06 67 ff ff jmp ffff678a <abs2\+0xfffecf14>
+[ ]*[a-f0-9]+: e9 06 67 ff ff jmp ffff678f <abs2\+0xfffecf19>
+[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 8a <glob\+0x85> 8a: R_386_PC32 \*ABS\*
+[ ]*[a-f0-9]+: e9 f7 67 ff ff jmp ffff688a <abs2\+0xfffed014>
+[ ]*[a-f0-9]+: e9 f7 67 ff ff jmp ffff688f <abs2\+0xfffed019>
+[ ]*[a-f0-9]+: e9 86 67 ff ff jmp ffff6823 <abs2\+0xfffecfad> 99: R_386_PC32 .data
+[ ]*[a-f0-9]+: e9 8a 67 ff ff jmp ffff682c <abs2\+0xfffecfb6> 9e: R_386_PC32 .data
+[ ]*[a-f0-9]+: e9 fc 00 00 00 jmp 1a3 <glob2\+0x9e> a3: R_386_PC32 \*ABS\*
+[ ]*[a-f0-9]+: e9 01 00 00 00 jmp ad <glob\+0xa8> a8: R_386_PC32 \*ABS\*
+[ ]*[a-f0-9]+: e9 01 ff ff ff jmp ffffffb2 <abs2\+0xffff673c> ad: R_386_PC32 \*ABS\*
+[ ]*[a-f0-9]+: e9 01 01 00 00 jmp 1b7 <glob2\+0xb2> b2: R_386_PC32 \*ABS\*
+[ ]*[a-f0-9]+: e9 01 00 00 00 jmp bc <glob\+0xb7> b7: R_386_PC32 \*ABS\*
+ ...
+#pass
+#as: -mshared
#objdump: -dwr
.*: +file format .*
Disassembly of section .text:
0+ <foo>:
-[ ]*[a-f0-9]+: eb 1f jmp 21 <local>
-[ ]*[a-f0-9]+: eb 19 jmp 1d <hidden_def>
-[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 5 <foo\+0x5> 5: (R_386_PC)?(DISP)?32 global_def
-[ ]*[a-f0-9]+: e9 fc ff ff ff jmp a <foo\+0xa> a: (R_386_PC)?(DISP)?32 weak_def
-[ ]*[a-f0-9]+: e9 fc ff ff ff jmp f <foo\+0xf> f: (R_386_PC)?(DISP)?32 weak_hidden_undef
-[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 14 <foo\+0x14> 14: (R_386_PC)?(DISP)?32 weak_hidden_def
-[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 19 <foo\+0x19> 19: (R_386_PC)?(DISP)?32 hidden_undef
-
-0+1d <hidden_def>:
+[ ]*[a-f0-9]+: eb 24 jmp 26 <local>
+[ ]*[a-f0-9]+: eb 1e jmp 22 <hidden_def>
+[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 5 <foo\+0x5> 5: R_386_PC32 global_def
+[ ]*[a-f0-9]+: e9 fc ff ff ff jmp a <foo\+0xa> a: R_386_PLT32 global_def
+[ ]*[a-f0-9]+: e9 fc ff ff ff jmp f <foo\+0xf> f: R_386_PC32 weak_def
+[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 14 <foo\+0x14> 14: R_386_PC32 weak_hidden_undef
+[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 19 <foo\+0x19> 19: R_386_PC32 weak_hidden_def
+[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 1e <foo\+0x1e> 1e: R_386_PC32 hidden_undef
+
+0+22 <hidden_def>:
[ ]*[a-f0-9]+: c3 ret
-0+1e <weak_hidden_def>:
+0+23 <weak_hidden_def>:
[ ]*[a-f0-9]+: c3 ret
-0+1f <global_def>:
+0+24 <global_def>:
[ ]*[a-f0-9]+: c3 ret
-0+20 <weak_def>:
+0+25 <weak_def>:
[ ]*[a-f0-9]+: c3 ret
-0+21 <local>:
+0+26 <local>:
[ ]*[a-f0-9]+: c3 ret
#pass
jmp local
jmp hidden_def
jmp global_def
+ jmp global_def@PLT
jmp weak_def
jmp weak_hidden_undef
jmp weak_hidden_def
--- /dev/null
+#source: relax-3.s
+#objdump: -dwr
+
+.*: +file format .*
+
+Disassembly of section .text:
+
+0+ <foo>:
+[ ]*[a-f0-9]+: eb 21 jmp 23 <local>
+[ ]*[a-f0-9]+: eb 1b jmp 1f <hidden_def>
+[ ]*[a-f0-9]+: eb 1b jmp 21 <global_def>
+[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 7 <foo\+0x7> 7: R_386_PLT32 global_def
+[ ]*[a-f0-9]+: e9 fc ff ff ff jmp c <foo\+0xc> c: R_386_PC32 weak_def
+[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 11 <foo\+0x11> 11: R_386_PC32 weak_hidden_undef
+[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 16 <foo\+0x16> 16: R_386_PC32 weak_hidden_def
+[ ]*[a-f0-9]+: e9 fc ff ff ff jmp 1b <foo\+0x1b> 1b: R_386_PC32 hidden_undef
+
+0+1f <hidden_def>:
+[ ]*[a-f0-9]+: c3 ret
+
+0+20 <weak_hidden_def>:
+[ ]*[a-f0-9]+: c3 ret
+
+0+21 <global_def>:
+[ ]*[a-f0-9]+: c3 ret
+
+0+22 <weak_def>:
+[ ]*[a-f0-9]+: c3 ret
+
+0+23 <local>:
+[ ]*[a-f0-9]+: c3 ret
+#pass
#source: relax-3.s
+#as: -mshared
#objdump: -dwr
.*: +file format .*
Disassembly of section .text:
0+ <foo>:
-[ ]*[a-f0-9]+: eb 1f jmp 21 <local>
-[ ]*[a-f0-9]+: eb 19 jmp 1d <hidden_def>
+[ ]*[a-f0-9]+: eb 24 jmp 26 <local>
+[ ]*[a-f0-9]+: eb 1e jmp 22 <hidden_def>
[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 9 <foo\+0x9> 5: R_X86_64_PC32 global_def-0x4
-[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq e <foo\+0xe> a: R_X86_64_PC32 weak_def-0x4
-[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 13 <foo\+0x13> f: R_X86_64_PC32 weak_hidden_undef-0x4
-[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 18 <foo\+0x18> 14: R_X86_64_PC32 weak_hidden_def-0x4
-[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 1d <hidden_def> 19: R_X86_64_PC32 hidden_undef-0x4
+[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq e <foo\+0xe> a: R_X86_64_PLT32 global_def-0x4
+[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 13 <foo\+0x13> f: R_X86_64_PC32 weak_def-0x4
+[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 18 <foo\+0x18> 14: R_X86_64_PC32 weak_hidden_undef-0x4
+[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 1d <foo\+0x1d> 19: R_X86_64_PC32 weak_hidden_def-0x4
+[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 22 <hidden_def> 1e: R_X86_64_PC32 hidden_undef-0x4
-0+1d <hidden_def>:
+0+22 <hidden_def>:
[ ]*[a-f0-9]+: c3 retq
-0+1e <weak_hidden_def>:
+0+23 <weak_hidden_def>:
[ ]*[a-f0-9]+: c3 retq
-0+1f <global_def>:
+0+24 <global_def>:
[ ]*[a-f0-9]+: c3 retq
-0+20 <weak_def>:
+0+25 <weak_def>:
[ ]*[a-f0-9]+: c3 retq
-0+21 <local>:
+0+26 <local>:
[ ]*[a-f0-9]+: c3 retq
#pass
--- /dev/null
+#source: relax-3.s
+#objdump: -dwr
+
+.*: +file format .*
+
+
+Disassembly of section .text:
+
+0+ <foo>:
+[ ]*[a-f0-9]+: eb 21 jmp 23 <local>
+[ ]*[a-f0-9]+: eb 1b jmp 1f <hidden_def>
+[ ]*[a-f0-9]+: eb 1b jmp 21 <global_def>
+[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq b <foo\+0xb> 7: R_X86_64_PLT32 global_def-0x4
+[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 10 <foo\+0x10> c: R_X86_64_PC32 weak_def-0x4
+[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 15 <foo\+0x15> 11: R_X86_64_PC32 weak_hidden_undef-0x4
+[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 1a <foo\+0x1a> 16: R_X86_64_PC32 weak_hidden_def-0x4
+[ ]*[a-f0-9]+: e9 00 00 00 00 jmpq 1f <hidden_def> 1b: R_X86_64_PC32 hidden_undef-0x4
+
+0+1f <hidden_def>:
+[ ]*[a-f0-9]+: c3 retq
+
+0+20 <weak_hidden_def>:
+[ ]*[a-f0-9]+: c3 retq
+
+0+21 <global_def>:
+[ ]*[a-f0-9]+: c3 retq
+
+0+22 <weak_def>:
+[ ]*[a-f0-9]+: c3 retq
+
+0+23 <local>:
+[ ]*[a-f0-9]+: c3 retq
+#pass