From d5ac0401eb128bf3dadec943741dfde7c499e49a Mon Sep 17 00:00:00 2001 From: Haochen Gui Date: Tue, 17 Nov 2020 13:52:15 -0600 Subject: [PATCH] Relocatable read-only section support for absolute jump table This patch puts absolute jump tables into a relocatable read-only section if they are on ELF target and relocation is supported. gcc/ChangeLog: * final.c (final_scan_insn_1): Set jump table relocatable as the second argument of targetm.asm_out.function_rodata_section. * output.h (default_function_rodata_section, default_no_function_rodata_section): Add the second argument to the declarations. * target.def (function_rodata_section): Change the doc and add the second argument. * doc/tm.texi: Regenerate. * varasm.c (jumptable_relocatable): Implement. (default_function_rodata_section): Add the second argument and the support for relocatable read only sections. (default_no_function_rodata_section): Add the second argument. (function_mergeable_rodata_prefix): Set the second argument to false. * config/mips/mips.c (mips_function_rodata_section): Add the second arugment and set it to false. * config/s390/s390.c (targetm.asm_out.function_rodata_section): Set the second argument to false. * config/s390/s390.md: Likewise. --- gcc/config/mips/mips.c | 4 +-- gcc/config/s390/s390.c | 2 +- gcc/config/s390/s390.md | 2 +- gcc/doc/tm.texi | 11 ++++--- gcc/final.c | 22 +++++++++++-- gcc/output.h | 4 +-- gcc/target.def | 14 ++++---- gcc/varasm.c | 71 ++++++++++++++++++++++++++++++----------- 8 files changed, 92 insertions(+), 38 deletions(-) diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 513fc5fe295..58e474e063d 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -9315,10 +9315,10 @@ mips_select_rtx_section (machine_mode mode, rtx x, default_function_rodata_section. */ static section * -mips_function_rodata_section (tree decl) +mips_function_rodata_section (tree decl, bool) { if (!TARGET_ABICALLS || TARGET_ABSOLUTE_ABICALLS || TARGET_GPWORD) - return default_function_rodata_section (decl); + return default_function_rodata_section (decl, false); if (decl && DECL_SECTION_NAME (decl)) { diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 2300a517b64..6983e363252 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -11746,7 +11746,7 @@ s390_output_split_stack_data (rtx parm_block, rtx call_done, rtx ops[] = { parm_block, call_done }; switch_to_section (targetm.asm_out.function_rodata_section - (current_function_decl)); + (current_function_decl, false)); if (TARGET_64BIT) output_asm_insn (".align\t8", NULL); diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index a2c033b2515..910415a5974 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -11290,7 +11290,7 @@ "" { switch_to_section (targetm.asm_out.function_rodata_section - (current_function_decl)); + (current_function_decl, false)); return ""; } [(set_attr "length" "0")]) diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index f7f82911f05..2b88f78944f 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -7711,13 +7711,14 @@ example, the function @code{foo} would be placed in @code{.text.foo}. Whatever the actual target object format, this is often good enough. @end deftypefn -@deftypefn {Target Hook} {section *} TARGET_ASM_FUNCTION_RODATA_SECTION (tree @var{decl}) -Return the readonly data section associated with -@samp{DECL_SECTION_NAME (@var{decl})}. +@deftypefn {Target Hook} {section *} TARGET_ASM_FUNCTION_RODATA_SECTION (tree @var{decl}, bool @var{relocatable}) +Return the readonly data or reloc readonly data section associated with +@samp{DECL_SECTION_NAME (@var{decl})}. @var{relocatable} selects the latter +over the former. The default version of this function selects @code{.gnu.linkonce.r.name} if the function's section is @code{.gnu.linkonce.t.name}, @code{.rodata.name} -if function is in @code{.text.name}, and the normal readonly-data section -otherwise. +or @code{.data.rel.ro.name} if function is in @code{.text.name}, and +the normal readonly-data or reloc readonly data section otherwise. @end deftypefn @deftypevr {Target Hook} {const char *} TARGET_ASM_MERGEABLE_RODATA_PREFIX diff --git a/gcc/final.c b/gcc/final.c index 80423d117d9..fc9a05e335f 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -81,6 +81,7 @@ along with GCC; see the file COPYING3. If not see #include "rtl-iter.h" #include "print-rtl.h" #include "function-abi.h" +#include "common/common-target.h" #ifdef XCOFF_DEBUGGING_INFO #include "xcoffout.h" /* Needed for external data declarations. */ @@ -2154,6 +2155,21 @@ asm_show_source (const char *filename, int linenum) fputc ('\n', asm_out_file); } +/* Judge if an absolute jump table is relocatable. */ + +bool +jumptable_relocatable (void) +{ + bool relocatable = false; + + if (!CASE_VECTOR_PC_RELATIVE + && !targetm.asm_out.generate_pic_addr_diff_vec () + && targetm_common.have_named_sections) + relocatable = targetm.asm_out.reloc_rw_mask (); + + return relocatable; +} + /* The final scan for one insn, INSN. Args are same as in `final', except that INSN is the insn being scanned. @@ -2493,7 +2509,8 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, int log_align; switch_to_section (targetm.asm_out.function_rodata_section - (current_function_decl)); + (current_function_decl, + jumptable_relocatable ())); #ifdef ADDR_VEC_ALIGN log_align = ADDR_VEC_ALIGN (table); @@ -2572,7 +2589,8 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, if (! JUMP_TABLES_IN_TEXT_SECTION) switch_to_section (targetm.asm_out.function_rodata_section - (current_function_decl)); + (current_function_decl, + jumptable_relocatable ())); else switch_to_section (current_function_section ()); diff --git a/gcc/output.h b/gcc/output.h index 2f2f1697fd8..b44c1bd6fc7 100644 --- a/gcc/output.h +++ b/gcc/output.h @@ -572,8 +572,8 @@ extern void default_ctor_section_asm_out_constructor (rtx, int); extern section *default_select_section (tree, int, unsigned HOST_WIDE_INT); extern section *default_elf_select_section (tree, int, unsigned HOST_WIDE_INT); extern void default_unique_section (tree, int); -extern section *default_function_rodata_section (tree); -extern section *default_no_function_rodata_section (tree); +extern section *default_function_rodata_section (tree, bool); +extern section *default_no_function_rodata_section (tree, bool); extern section *default_clone_table_section (void); extern section *default_select_rtx_section (machine_mode, rtx, unsigned HOST_WIDE_INT); diff --git a/gcc/target.def b/gcc/target.def index ff7ad5983ac..810d5542c28 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -559,16 +559,18 @@ Whatever the actual target object format, this is often good enough.", void, (tree decl, int reloc), default_unique_section) -/* Return the readonly data section associated with function DECL. */ +/* Return the readonly data or relocated readonly data section + associated with function DECL. */ DEFHOOK (function_rodata_section, - "Return the readonly data section associated with\n\ -@samp{DECL_SECTION_NAME (@var{decl})}.\n\ + "Return the readonly data or reloc readonly data section associated with\n\ +@samp{DECL_SECTION_NAME (@var{decl})}. @var{relocatable} selects the latter\n\ +over the former.\n\ The default version of this function selects @code{.gnu.linkonce.r.name} if\n\ the function's section is @code{.gnu.linkonce.t.name}, @code{.rodata.name}\n\ -if function is in @code{.text.name}, and the normal readonly-data section\n\ -otherwise.", - section *, (tree decl), +or @code{.data.rel.ro.name} if function is in @code{.text.name}, and\n\ +the normal readonly-data or reloc readonly data section otherwise.", + section *, (tree decl, bool relocatable), default_function_rodata_section) /* Nonnull if the target wants to override the default ".rodata" prefix diff --git a/gcc/varasm.c b/gcc/varasm.c index 435c7b348a5..ada99940f65 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -732,12 +732,26 @@ switch_to_other_text_partition (void) switch_to_section (current_function_section ()); } -/* Return the read-only data section associated with function DECL. */ +/* Return the read-only or relocated read-only data section + associated with function DECL. */ section * -default_function_rodata_section (tree decl) +default_function_rodata_section (tree decl, bool relocatable) { - if (decl != NULL_TREE && DECL_SECTION_NAME (decl)) + const char* sname; + unsigned int flags; + + flags = 0; + + if (relocatable) + { + sname = ".data.rel.ro.local"; + flags = (SECTION_WRITE | SECTION_RELRO); + } + else + sname = ".rodata"; + + if (decl && DECL_SECTION_NAME (decl)) { const char *name = DECL_SECTION_NAME (decl); @@ -750,38 +764,56 @@ default_function_rodata_section (tree decl) dot = strchr (name + 1, '.'); if (!dot) dot = name; - len = strlen (dot) + 8; + len = strlen (dot) + strlen (sname) + 1; rname = (char *) alloca (len); - strcpy (rname, ".rodata"); + strcpy (rname, sname); strcat (rname, dot); - return get_section (rname, SECTION_LINKONCE, decl); + return get_section (rname, (SECTION_LINKONCE | flags), decl); } - /* For .gnu.linkonce.t.foo we want to use .gnu.linkonce.r.foo. */ + /* For .gnu.linkonce.t.foo we want to use .gnu.linkonce.r.foo or + .gnu.linkonce.d.rel.ro.local.foo if the jump table is relocatable. */ else if (DECL_COMDAT_GROUP (decl) && strncmp (name, ".gnu.linkonce.t.", 16) == 0) { - size_t len = strlen (name) + 1; - char *rname = (char *) alloca (len); + size_t len; + char *rname; - memcpy (rname, name, len); - rname[14] = 'r'; - return get_section (rname, SECTION_LINKONCE, decl); + if (relocatable) + { + len = strlen (name) + strlen (".rel.ro.local") + 1; + rname = (char *) alloca (len); + + strcpy (rname, ".gnu.linkonce.d.rel.ro.local"); + strcat (rname, name + 15); + } + else + { + len = strlen (name) + 1; + rname = (char *) alloca (len); + + memcpy (rname, name, len); + rname[14] = 'r'; + } + return get_section (rname, (SECTION_LINKONCE | flags), decl); } /* For .text.foo we want to use .rodata.foo. */ else if (flag_function_sections && flag_data_sections && strncmp (name, ".text.", 6) == 0) { size_t len = strlen (name) + 1; - char *rname = (char *) alloca (len + 2); + char *rname = (char *) alloca (len + strlen (sname) - 5); - memcpy (rname, ".rodata", 7); - memcpy (rname + 7, name + 5, len - 5); - return get_section (rname, 0, decl); + memcpy (rname, sname, strlen (sname)); + memcpy (rname + strlen (sname), name + 5, len - 5); + return get_section (rname, flags, decl); } } - return readonly_data_section; + if (relocatable) + return get_section (sname, flags, decl); + else + return readonly_data_section; } /* Return the read-only data section associated with function DECL @@ -789,7 +821,7 @@ default_function_rodata_section (tree decl) readonly data section. */ section * -default_no_function_rodata_section (tree decl ATTRIBUTE_UNUSED) +default_no_function_rodata_section (tree, bool) { return readonly_data_section; } @@ -799,7 +831,8 @@ default_no_function_rodata_section (tree decl ATTRIBUTE_UNUSED) static const char * function_mergeable_rodata_prefix (void) { - section *s = targetm.asm_out.function_rodata_section (current_function_decl); + section *s = targetm.asm_out.function_rodata_section (current_function_decl, + false); if (SECTION_STYLE (s) == SECTION_NAMED) return s->named.name; else -- 2.30.2