Use the section flag 'o' for __patchable_function_entries
authorH.J. Lu <hjl.tools@gmail.com>
Wed, 2 Dec 2020 13:32:37 +0000 (05:32 -0800)
committerH.J. Lu <hjl.tools@gmail.com>
Wed, 2 Dec 2020 13:32:37 +0000 (05:32 -0800)
This commit in GNU binutils 2.35:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=b7d072167715829eed0622616f6ae0182900de3e

added the section flag 'o' to .section directive:

.section __patchable_function_entries,"awo",@progbits,foo

which specifies the symbol name which the section references.  Assembler
creates a unique __patchable_function_entries section with the section,
where foo is defined, as its linked-to section.  Linker keeps a section
if its linked-to section is kept during garbage collection.

This patch checks assembler support for the section flag 'o' and uses
it to implement __patchable_function_entries section.  Since Solaris may
use GNU assembler with Solairs ld.  Even if GNU assembler supports the
section flag 'o', it doesn't mean that Solairs ld supports it.  This
feature is disabled for Solairs targets.

gcc/

PR middle-end/93195
PR middle-end/93197
* configure.ac (HAVE_GAS_SECTION_LINK_ORDER): New.  Define 1 if
the assembler supports the section flag 'o' for specifying
section with link-order.
* output.h (SECTION_LINK_ORDER): New.  Defined to 0x8000000.
(SECTION_MACH_DEP): Changed from 0x8000000 to 0x10000000.
* targhooks.c (default_print_patchable_function_entry): Pass
SECTION_LINK_ORDER to switch_to_section if the section flag 'o'
works.  Pass current_function_decl to switch_to_section.
* varasm.c (default_elf_asm_named_section): Use 'o' flag for
SECTION_LINK_ORDER if assembler supports it.
* config.in: Regenerated.
* configure: Likewise.
* doc/sourcebuild.texi: Document o_flag_in_section.

gcc/testsuite/

PR middle-end/93195
* g++.dg/pr93195a.C: New test.
* g++.dg/pr93195b.C: Likewise.
* lib/target-supports.exp
(check_effective_target_o_flag_in_section): New proc.

gcc/config.in
gcc/configure
gcc/configure.ac
gcc/doc/sourcebuild.texi
gcc/output.h
gcc/targhooks.c
gcc/testsuite/g++.dg/pr93195a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/pr93195b.C [new file with mode: 0644]
gcc/testsuite/lib/target-supports.exp
gcc/varasm.c

index b6e041d311eef73abc0caf6f376afa3f28543994..216505abd2c54ead937387d798ec556c3175b6c7 100644 (file)
 #endif
 
 
+/* Define 0/1 if your assembler supports 'o' flag in .section directive. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_SECTION_LINK_ORDER
+#endif
+
+
 /* Define 0/1 if your assembler supports marking sections with SHF_GNU_RETAIN
    flag. */
 #ifndef USED_FOR_TARGET
index 747822208f2517256a1da1a1d5566c8c20aafe15..785d6560987a2865a0a490f5e992cee2fd65dd03 100755 (executable)
@@ -24481,6 +24481,58 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+# Test if the assembler supports the section flag 'o' for specifying
+# section with link-order.
+case "${target}" in
+  # Solaris may use GNU assembler with Solairs ld.  Even if GNU
+  # assembler supports the section flag 'o', it doesn't mean that
+  # Solairs ld supports it.
+  *-*-solaris2*)
+    gcc_cv_as_section_link_order=no
+    ;;
+  *)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section 'o' flag" >&5
+$as_echo_n "checking assembler for section 'o' flag... " >&6; }
+if ${gcc_cv_as_section_link_order+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_section_link_order=no
+    if test $in_tree_gas = yes; then
+    if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 35 \) \* 1000 + 0`
+  then gcc_cv_as_section_link_order=yes
+fi
+  elif test x$gcc_cv_as != x; then
+    $as_echo '.section .foo,"a"
+.byte 0
+.section __patchable_function_entries,"awo",%progbits,.foo
+.byte 0' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags --fatal-warnings -o conftest.o conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+       gcc_cv_as_section_link_order=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_section_link_order" >&5
+$as_echo "$gcc_cv_as_section_link_order" >&6; }
+
+
+    ;;
+esac
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GAS_SECTION_LINK_ORDER `if test $gcc_cv_as_section_link_order = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for section merging support" >&5
 $as_echo_n "checking assembler for section merging support... " >&6; }
 if ${gcc_cv_as_shf_merge+:} false; then :
index 478d0d6f238c1a587c3f07c936da96232472f09a..062f57fa12b78eabbf07fb21e22bf4380bbf06af 100644 (file)
@@ -3350,6 +3350,28 @@ AC_DEFINE_UNQUOTED(HAVE_GAS_SHF_GNU_RETAIN,
   [`if test $gcc_cv_as_shf_gnu_retain = yes; then echo 1; else echo 0; fi`],
   [Define 0/1 if your assembler supports marking sections with SHF_GNU_RETAIN flag.])
 
+# Test if the assembler supports the section flag 'o' for specifying
+# section with link-order.
+case "${target}" in
+  # Solaris may use GNU assembler with Solairs ld.  Even if GNU
+  # assembler supports the section flag 'o', it doesn't mean that
+  # Solairs ld supports it.
+  *-*-solaris2*)
+    gcc_cv_as_section_link_order=no
+    ;;
+  *)
+    gcc_GAS_CHECK_FEATURE([section 'o' flag], gcc_cv_as_section_link_order,
+      [2,35,0], [--fatal-warnings],
+      [.section .foo,"a"
+.byte 0
+.section __patchable_function_entries,"awo",%progbits,.foo
+.byte 0])
+    ;;
+esac
+AC_DEFINE_UNQUOTED(HAVE_GAS_SECTION_LINK_ORDER,
+  [`if test $gcc_cv_as_section_link_order = yes; then echo 1; else echo 0; fi`],
+  [Define 0/1 if your assembler supports 'o' flag in .section directive.])
+
 gcc_GAS_CHECK_FEATURE(section merging support, gcc_cv_as_shf_merge,
  [elf,2,12,0], [--fatal-warnings],
  [.section .rodata.str, "aMS", @progbits, 1])
index 55538c3586b4a421b0e250b669f250f9b330b139..586dce75740af97a4d536423441918ff0fa53894 100644 (file)
@@ -2548,6 +2548,9 @@ Target supports the @code{noinit} variable attribute.
 @item nonpic
 Target does not generate PIC by default.
 
+@item o_flag_in_section
+Target supports the 'o' flag in .section directive in assembly inputs.
+
 @item offload_gcn
 Target has been configured for OpenACC/OpenMP offloading on AMD GCN.
 
index 729c52099e6b6fa0362e7b9fdf6728ec7874ad24..fa8ace1f394bf0a714c87fa0fa19fc6b54b7e1e3 100644 (file)
@@ -382,10 +382,11 @@ extern void no_asm_to_stream (FILE *);
 #define SECTION_RELRO   0x1000000      /* data is readonly after relocation processing */
 #define SECTION_EXCLUDE  0x2000000     /* discarded by the linker */
 #define SECTION_RETAIN  0x4000000      /* retained by the linker.  */
+#define SECTION_LINK_ORDER 0x8000000   /* section needs link-order.  */
 
 /* NB: The maximum SECTION_MACH_DEP is 0x10000000 since AVR needs 4 bits
    in SECTION_MACH_DEP.  */
-#define SECTION_MACH_DEP 0x8000000     /* subsequent bits reserved for target */
+#define SECTION_MACH_DEP 0x10000000    /* subsequent bits reserved for target */
 
 /* This SECTION_STYLE is used for unnamed sections that we can switch
    to using a special assembler directive.  */
index e634df3f6c6837e422246a7736c0de4471ce1e77..6e12e13d68e1a0a0eabf497c86f6d821bedfc449 100644 (file)
@@ -1864,8 +1864,11 @@ default_print_patchable_function_entry (FILE *file,
       patch_area_number++;
       ASM_GENERATE_INTERNAL_LABEL (buf, "LPFE", patch_area_number);
 
+      unsigned int flags = SECTION_WRITE | SECTION_RELRO;
+      if (HAVE_GAS_SECTION_LINK_ORDER)
+       flags |= SECTION_LINK_ORDER;
       switch_to_section (get_section ("__patchable_function_entries",
-                                     SECTION_WRITE | SECTION_RELRO, NULL));
+                                     flags, current_function_decl));
       assemble_align (POINTER_SIZE);
       fputs (asm_op, file);
       assemble_name_raw (file, buf);
diff --git a/gcc/testsuite/g++.dg/pr93195a.C b/gcc/testsuite/g++.dg/pr93195a.C
new file mode 100644 (file)
index 0000000..26d265d
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-do link { target { ! { nvptx*-*-* visium-*-* } } } } */
+// { dg-require-effective-target o_flag_in_section }
+/* { dg-options "-O0 -fpatchable-function-entry=1" } */
+/* { dg-additional-options "-fno-pie" { target sparc*-*-* } } */
+/* { dg-additional-sources pr93195b.C } */
+
+extern void bar1 (void);
+
+inline void
+foo (void)
+{
+}
+
+void
+bar (void)
+{
+  foo ();
+  bar1 ();
+}
+
+int
+main ()
+{
+  bar ();
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/pr93195b.C b/gcc/testsuite/g++.dg/pr93195b.C
new file mode 100644 (file)
index 0000000..303d858
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { ! { nvptx*-*-* visium-*-* } } } } */
+/* { dg-options "-O0 -fpatchable-function-entry=1" } */
+/* { dg-additional-options "-fno-pie" { target sparc*-*-* } } */
+
+inline void
+foo (void)
+{
+}
+
+void
+bar1 (void)
+{
+  foo ();
+}
index 9d0a25d77e579bdf5b4a7127583385a3c71fcc81..89c4f67554f6da90fe420694ec2a61e6770f04a8 100644 (file)
@@ -10702,3 +10702,43 @@ proc check_effective_target_R_flag_in_section { } {
        }
     }]
 }
+
+# Return 1 if this target supports 'o' flag in .section directive, 0
+# otherwise.  Cache the result.
+
+proc check_effective_target_o_flag_in_section { } {
+    global tool
+    global GCC_UNDER_TEST
+
+    # Need auto-host.h to check linker support.
+    if { ![file exists ../../auto-host.h ] } {
+       return 0
+    }
+
+    return [check_cached_effective_target o_flag_in_section {
+
+       set src pie[pid].c
+       set obj pie[pid].o
+
+       set f [open $src "w"]
+       puts $f "#include \"../../auto-host.h\""
+       puts $f "#if HAVE_GAS_SECTION_LINK_ORDER == 0"
+       puts $f "# error Assembler does not support 'o' flag in .section directive."
+       puts $f "#endif"
+       close $f
+
+       verbose "check_effective_target_o_flag_in_section compiling testfile $src" 2
+       set lines [${tool}_target_compile $src $obj object ""]
+
+       file delete $src
+       file delete $obj
+
+       if [string match "" $lines] then {
+           verbose "check_effective_target_o_flag_in_section testfile compilation passed" 2
+           return 1
+       } else {
+           verbose "check_effective_target_o_flag_in_section testfile compilation failed" 2
+           return 0
+       }
+    }]
+}
index 6c13f528f7b839c236cab104b7d8a73cfd1c4cec..961d2d6fe3ba90a4827c4e3ae57a3fae79de345c 100644 (file)
@@ -6789,6 +6789,8 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
        *f++ = 'G';
       if (flags & SECTION_RETAIN)
        *f++ = 'R';
+      if (flags & SECTION_LINK_ORDER)
+       *f++ = 'o';
 #ifdef MACH_DEP_SECTION_ASM_FLAG
       if (flags & SECTION_MACH_DEP)
        *f++ = MACH_DEP_SECTION_ASM_FLAG;
@@ -6821,6 +6823,14 @@ default_elf_asm_named_section (const char *name, unsigned int flags,
 
       if (flags & SECTION_ENTSIZE)
        fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE);
+      if (flags & SECTION_LINK_ORDER)
+       {
+         tree id = DECL_ASSEMBLER_NAME (decl);
+         ultimate_transparent_alias_target (&id);
+         const char *name = IDENTIFIER_POINTER (id);
+         name = targetm.strip_name_encoding (name);
+         fprintf (asm_out_file, ",%s", name);
+       }
       if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
        {
          if (TREE_CODE (decl) == IDENTIFIER_NODE)