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 if the assembler supports the section flag 'o' for specifying section with link-order. * dwarf2out.c (output_comdat_type_unit): Pass 0 as flags2 to targetm.asm_out.named_section. * config/sol2.c (solaris_elf_asm_comdat_section): Likewise. * output.h (SECTION2_LINK_ORDER): New. (switch_to_section): Add an unsigned int argument. (default_no_named_section): Likewise. (default_elf_asm_named_section): Likewise. * target.def (asm_out.named_section): Likewise. * targhooks.c (default_print_patchable_function_entry): Pass current_function_decl to get_section and SECTION2_LINK_ORDER to switch_to_section. * varasm.c (default_no_named_section): Add an unsigned int argument. (default_elf_asm_named_section): Add an unsigned int argument, flags2. Use 'o' flag for SECTION2_LINK_ORDER if assembler supports it. (switch_to_section): Add an unsigned int argument and pass it to targetm.asm_out.named_section. (handle_vtv_comdat_section): Pass 0 to targetm.asm_out.named_section. * config.in: Regenerated. * configure: Likewise. * doc/tm.texi: Likewise. 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 | 6 ++++ gcc/config/sol2.c | 3 +- gcc/configure | 52 +++++++++++++++++++++++++++ gcc/configure.ac | 22 ++++++++++++ gcc/doc/tm.texi | 5 +-- gcc/dwarf2out.c | 4 +-- gcc/output.h | 11 ++++-- gcc/target.def | 5 +-- gcc/targhooks.c | 4 ++- gcc/testsuite/g++.dg/pr93195a.C | 27 ++++++++++++++ gcc/testsuite/g++.dg/pr93195b.C | 14 ++++++++ gcc/testsuite/lib/target-supports.exp | 40 +++++++++++++++++++++ gcc/varasm.c | 25 ++++++++++--- 13 files changed, 202 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/g++.dg/pr93195a.C create mode 100644 gcc/testsuite/g++.dg/pr93195b.C diff --git a/gcc/config.in b/gcc/config.in index 48292861842..d1ecc5b15a6 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -1313,6 +1313,12 @@ #endif +/* Define 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_MERGE flag. */ #ifndef USED_FOR_TARGET diff --git a/gcc/config/sol2.c b/gcc/config/sol2.c index cf9d9f1f684..62bbdec2f97 100644 --- a/gcc/config/sol2.c +++ b/gcc/config/sol2.c @@ -224,7 +224,8 @@ solaris_elf_asm_comdat_section (const char *name, unsigned int flags, tree decl) emits this as a regular section. Emit section before .group directive since Sun as treats undeclared sections as @progbits, which conflicts with .bss* sections which are @nobits. */ - targetm.asm_out.named_section (section, flags & ~SECTION_LINKONCE, decl); + targetm.asm_out.named_section (section, flags & ~SECTION_LINKONCE, + 0, decl); /* Sun as separates declaration of a group section and of the group itself, using the .group directive and the #comdat flag. */ diff --git a/gcc/configure b/gcc/configure index 5fa565a40a4..a7315e33a62 100755 --- a/gcc/configure +++ b/gcc/configure @@ -24185,6 +24185,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 : diff --git a/gcc/configure.ac b/gcc/configure.ac index 671b9a67d81..5619736ee0c 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -3199,6 +3199,28 @@ AC_DEFINE_UNQUOTED(HAVE_GAS_SECTION_EXCLUDE, [`if test $gcc_cv_as_section_exclude_e = yes || test $gcc_cv_as_section_exclude_hash = yes; then echo 1; else echo 0; fi`], [Define if your assembler supports specifying the exclude section 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 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]) diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 19985adac3e..f50ce812a1d 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -8003,9 +8003,10 @@ the assembler source. So you can use it to canonicalize the format of the filename using this macro. @end defmac -@deftypefn {Target Hook} void TARGET_ASM_NAMED_SECTION (const char *@var{name}, unsigned int @var{flags}, tree @var{decl}) +@deftypefn {Target Hook} void TARGET_ASM_NAMED_SECTION (const char *@var{name}, unsigned int @var{flags}, unsigned int @var{flags2}, tree @var{decl}) Output assembly directives to switch to section @var{name}. The section -should have attributes as specified by @var{flags}, which is a bit mask +should have attributes as specified by @var{flags} and @var{flags2}, +which are bit masks of the @code{SECTION_*} flags defined in @file{output.h}. If @var{decl} is non-NULL, it is the @code{VAR_DECL} or @code{FUNCTION_DECL} with which this section is associated. diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index fe46c7e1eee..1b0dd2364bb 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -11303,7 +11303,7 @@ output_comdat_type_unit (comdat_type_node *node, comdat_key = get_identifier (tmp); targetm.asm_out.named_section (secname, SECTION_DEBUG | SECTION_LINKONCE, - comdat_key); + 0, comdat_key); #else tmp = XALLOCAVEC (char, 18 + DWARF_TYPE_SIGNATURE_SIZE * 2); sprintf (tmp, (dwarf_version >= 5 @@ -28511,7 +28511,7 @@ output_macinfo (const char *debug_line_label, bool early_lto_debug) | SECTION_LINKONCE | (early_lto_debug ? SECTION_EXCLUDE : 0), - comdat_key); + 0, comdat_key); ASM_GENERATE_INTERNAL_LABEL (label, DEBUG_MACRO_SECTION_LABEL, ref->lineno + macinfo_label_base); diff --git a/gcc/output.h b/gcc/output.h index eb253c50329..becbeadc8ea 100644 --- a/gcc/output.h +++ b/gcc/output.h @@ -396,6 +396,9 @@ extern void no_asm_to_stream (FILE *); to declare the object. */ #define SECTION_NOSWITCH 0x400000 +/* Flags2 controlling properties of a section. */ +#define SECTION2_LINK_ORDER 0x00000001 /* section needs link-order. */ + /* A helper function for default_elf_select_section and default_elf_unique_section. Categorizes the DECL. */ @@ -542,7 +545,7 @@ extern void switch_to_other_text_partition (void); extern section *get_cdtor_priority_section (int, bool); extern bool unlikely_text_section_p (section *); -extern void switch_to_section (section *); +extern void switch_to_section (section *, unsigned int = 0); extern void output_section_asm_op (const void *); extern void record_tm_clone_pair (tree, tree); @@ -557,8 +560,10 @@ extern unsigned int default_section_type_flags (tree, const char *, int); extern bool have_global_bss_p (void); extern bool bss_initializer_p (const_tree, bool = false); -extern void default_no_named_section (const char *, unsigned int, tree); -extern void default_elf_asm_named_section (const char *, unsigned int, tree); +extern void default_no_named_section (const char *, unsigned int, + unsigned int, tree); +extern void default_elf_asm_named_section (const char *, unsigned int, + unsigned int, tree); extern enum section_category categorize_decl_for_section (const_tree, int); extern void default_coff_asm_named_section (const char *, unsigned int, tree); extern void default_pe_asm_named_section (const char *, unsigned int, tree); diff --git a/gcc/target.def b/gcc/target.def index b5e82ff826e..97d53c909cf 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -414,11 +414,12 @@ described below.", DEFHOOK (named_section, "Output assembly directives to switch to section @var{name}. The section\n\ -should have attributes as specified by @var{flags}, which is a bit mask\n\ +should have attributes as specified by @var{flags} and @var{flags2},\n\ +which are bit masks\n\ of the @code{SECTION_*} flags defined in @file{output.h}. If @var{decl}\n\ is non-NULL, it is the @code{VAR_DECL} or @code{FUNCTION_DECL} with which\n\ this section is associated.", - void, (const char *name, unsigned int flags, tree decl), + void, (const char *name, unsigned int flags, unsigned int flags2, tree decl), default_no_named_section) /* Tell assembler what section attributes to assign this elf section diff --git a/gcc/targhooks.c b/gcc/targhooks.c index 7cb04f30bdb..0bae7bad1d4 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -1811,7 +1811,9 @@ default_print_patchable_function_entry (FILE *file, ASM_GENERATE_INTERNAL_LABEL (buf, "LPFE", patch_area_number); switch_to_section (get_section ("__patchable_function_entries", - SECTION_WRITE | SECTION_RELRO, NULL)); + SECTION_WRITE | SECTION_RELRO, + current_function_decl), + SECTION2_LINK_ORDER); 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 index 00000000000..26d265da74e --- /dev/null +++ b/gcc/testsuite/g++.dg/pr93195a.C @@ -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 index 00000000000..303d8588c0f --- /dev/null +++ b/gcc/testsuite/g++.dg/pr93195b.C @@ -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 (); +} diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index d3b2798df3e..ca3835204eb 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -9872,3 +9872,43 @@ proc check_effective_target_indirect_calls { } { } return 1 } + +# 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 + } + }] +} diff --git a/gcc/varasm.c b/gcc/varasm.c index dc6da6c0b5b..8c9dc9dd476 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -6507,6 +6507,7 @@ have_global_bss_p (void) void default_no_named_section (const char *name ATTRIBUTE_UNUSED, unsigned int flags ATTRIBUTE_UNUSED, + unsigned int flags2 ATTRIBUTE_UNUSED, tree decl ATTRIBUTE_UNUSED) { /* Some object formats don't support named sections at all. The @@ -6520,7 +6521,7 @@ default_no_named_section (const char *name ATTRIBUTE_UNUSED, void default_elf_asm_named_section (const char *name, unsigned int flags, - tree decl) + unsigned int flags2, tree decl) { char flagchars[11], *f = flagchars; unsigned int numeric_value = 0; @@ -6562,6 +6563,10 @@ default_elf_asm_named_section (const char *name, unsigned int flags, *f++ = TLS_SECTION_ASM_FLAG; if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE)) *f++ = 'G'; +#if HAVE_GAS_SECTION_LINK_ORDER + if (flags2 & SECTION2_LINK_ORDER) + *f++ = 'o'; +#endif #ifdef MACH_DEP_SECTION_ASM_FLAG if (flags & SECTION_MACH_DEP) *f++ = MACH_DEP_SECTION_ASM_FLAG; @@ -6594,6 +6599,16 @@ default_elf_asm_named_section (const char *name, unsigned int flags, if (flags & SECTION_ENTSIZE) fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE); +#if HAVE_GAS_SECTION_LINK_ORDER + if (flags2 & SECTION2_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); + } +#endif if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE)) { if (TREE_CODE (decl) == IDENTIFIER_NODE) @@ -7462,7 +7477,7 @@ output_section_asm_op (const void *directive) the current section is NEW_SECTION. */ void -switch_to_section (section *new_section) +switch_to_section (section *new_section, unsigned int flags2) { if (in_section == new_section) return; @@ -7477,7 +7492,7 @@ switch_to_section (section *new_section) case SECTION_NAMED: targetm.asm_out.named_section (new_section->named.name, new_section->named.common.flags, - new_section->named.decl); + flags2, new_section->named.decl); break; case SECTION_UNNAMED: @@ -8145,7 +8160,7 @@ handle_vtv_comdat_section (section *sect, const_tree decl ATTRIBUTE_UNUSED) targetm.asm_out.named_section (sect->named.name, sect->named.common.flags | SECTION_LINKONCE, - DECL_NAME (decl)); + 0, DECL_NAME (decl)); in_section = sect; #else /* Neither OBJECT_FORMAT_PE, nor OBJECT_FORMAT_COFF is set here. @@ -8171,7 +8186,7 @@ handle_vtv_comdat_section (section *sect, const_tree decl ATTRIBUTE_UNUSED) targetm.asm_out.named_section (name, sect->named.common.flags | SECTION_LINKONCE, - DECL_NAME (decl)); + 0, DECL_NAME (decl)); in_section = sect; } else -- 2.24.1