diff mbox series

Put absolute address jump table in data.rel.ro.local if targets support relocations

Message ID b66686d7-6796-fcc3-b3b4-2a5f1c3ba197@linux.ibm.com
State New
Headers show
Series Put absolute address jump table in data.rel.ro.local if targets support relocations | expand

Commit Message

HAO CHEN GUI Sept. 14, 2020, 3:01 a.m. UTC
Hi,

   Jump tables are put into text or rodata section originally. On some 
platforms, it gains the performance benefit from absolute address jump 
tables. So I want to let absolute address jump table be relocatable.  
This patch puts absolute jump table in read only relocation section if 
the target supports relocations.

         /* Judge if it's a absolute jump table. Set relocatable for
            absolute jump table if the target supports relocations.  */

         if (!CASE_VECTOR_PC_RELATIVE
             && !targetm.asm_out.generate_pic_addr_diff_vec ())
            relocatable = targetm.asm_out.reloc_rw_mask ();

         switch_to_section (targetm.asm_out.function_rodata_section

                                       (current_function_decl, 
relocatable));

The attachments are the patch diff file and change log file.

Bootstrapped and tested on powerpc64le-linux-gnu with no regressions.  
Is this okay for trunk? Any recommendations? Thanks a lot.
* final.c (final_scan_insn_1): Judge if a jump table is relative or
	absoluted, and if it needs to be relocated.
	* 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 (default_function_rodata_section): Add the second argument
	to default_function_rodata_section. It indicates the section should be
	read-only or relocated read-only.
	(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/rs6000/linux64.h (JUMP_TABLES_IN_TEXT_SECTION): Define.

Comments

HAO CHEN GUI Sept. 28, 2020, 12:52 a.m. UTC | #1
Hi,

Gentle ping this:

https://gcc.gnu.org/pipermail/gcc-patches/2020-September/553809.html

Thanks

Gui Haochen

On 14/9/2020 上午 11:01, HAO CHEN GUI wrote:
> Hi,
>
>   Jump tables are put into text or rodata section originally. On some 
> platforms, it gains the performance benefit from absolute address jump 
> tables. So I want to let absolute address jump table be relocatable.  
> This patch puts absolute jump table in read only relocation section if 
> the target supports relocations.
>
>         /* Judge if it's a absolute jump table. Set relocatable for
>            absolute jump table if the target supports relocations.  */
>
>         if (!CASE_VECTOR_PC_RELATIVE
>             && !targetm.asm_out.generate_pic_addr_diff_vec ())
>            relocatable = targetm.asm_out.reloc_rw_mask ();
>
>         switch_to_section (targetm.asm_out.function_rodata_section
>
>                                       (current_function_decl, 
> relocatable));
>
> The attachments are the patch diff file and change log file.
>
> Bootstrapped and tested on powerpc64le-linux-gnu with no regressions.  
> Is this okay for trunk? Any recommendations? Thanks a lot.
>
Richard Sandiford Oct. 1, 2020, 5:47 p.m. UTC | #2
Sorry for the slow review.

HAO CHEN GUI via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
> diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
> index 513fc5fe295..6f5bf8d7d73 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 relocatable ATTRIBUTE_UNUSED)

Now that we're C++, it's more idiomatic to leave off the parameter name:

  mips_function_rodata_section (tree decl, bool)

Same for the rest of the patch.

> @@ -2491,9 +2491,19 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
>  	  if (! JUMP_TABLES_IN_TEXT_SECTION)
>  	    {
>  	      int log_align;
> +	      bool relocatable;
> +
> +	      relocatable = 0;

Very minor, but simpler as:

   bool relocatable = false;

Same for the later hunk.

> @@ -549,16 +549,17 @@ 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 or relocated readonly data section
> +   associated with function DECL.  */
>  DEFHOOK
>  (function_rodata_section,
> - "Return the readonly data section associated with\n\
> + "Return the readonly or reloc readonly data section associated with\n\
>  @samp{DECL_SECTION_NAME (@var{decl})}.\n\

Maybe add “; @var{relocatable} selects the latter over the former.”

>  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 4070f9c17e8..91ab75aed06 100644
> --- a/gcc/varasm.c
> +++ b/gcc/varasm.c
> @@ -726,12 +726,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);
>  
> @@ -744,12 +758,12 @@ 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.  */
>        else if (DECL_COMDAT_GROUP (decl)
> @@ -767,15 +781,18 @@ default_function_rodata_section (tree decl)
>  	       && 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);
>  	}
>      }

Don't we need to handle the .gnu.linkonce.t. case too?  I believe
the suffix there is “.d.rel.ro.local” (replacing “.t”)

My main concern is how this interacts with non-ELF targets.
It looks like AIX/XCOFF, Darwin and Cygwin already pick
default_no_function_rodata_section, so they should be fine.
But at the moment, all the fancy stuff in default_function_rodata_section
is indirectly guarded by targetm_common.have_named_sections, with the
hook falling back to readonly_data_section if the function isn't in a
named section.

So I wonder if it would be safer to test targetm_common.have_named_sections
in this condition:

> +
> +	      /* Judge if it's a absolute jump table. Set relocatable for
> +		 absolute jump table if the target supports relocations.  */
> +
> +	      if (!CASE_VECTOR_PC_RELATIVE
> +		  && !targetm.asm_out.generate_pic_addr_diff_vec ())
> +		relocatable = targetm.asm_out.reloc_rw_mask ();
>  
>  	      switch_to_section (targetm.asm_out.function_rodata_section
> -				 (current_function_decl));
> +				 (current_function_decl, relocatable));
>  
>  #ifdef ADDR_VEC_ALIGN
>  	      log_align = ADDR_VEC_ALIGN (table);

Similarly for the other case where the condition appears.  I think the
condition is subtle enough that it's worth splitting out into a helper.

Thanks,
Richard
HAO CHEN GUI Oct. 22, 2020, 2:53 a.m. UTC | #3
I had a wrong email setting and got your reply later. I modified the 
patch according to your advice. Could you please review it again? Thanks.

On 2/10/2020 上午 1:47, Richard Sandiford wrote:
> Sorry for the slow review.
>
> HAO CHEN GUI via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
>> diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
>> index 513fc5fe295..6f5bf8d7d73 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 relocatable ATTRIBUTE_UNUSED)
> Now that we're C++, it's more idiomatic to leave off the parameter name:
>
>    mips_function_rodata_section (tree decl, bool)
>
> Same for the rest of the patch.
>
>> @@ -2491,9 +2491,19 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
>>   	  if (! JUMP_TABLES_IN_TEXT_SECTION)
>>   	    {
>>   	      int log_align;
>> +	      bool relocatable;
>> +
>> +	      relocatable = 0;
> Very minor, but simpler as:
>
>     bool relocatable = false;
>
> Same for the later hunk.
>
>> @@ -549,16 +549,17 @@ 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 or relocated readonly data section
>> +   associated with function DECL.  */
>>   DEFHOOK
>>   (function_rodata_section,
>> - "Return the readonly data section associated with\n\
>> + "Return the readonly or reloc readonly data section associated with\n\
>>   @samp{DECL_SECTION_NAME (@var{decl})}.\n\
> Maybe add “; @var{relocatable} selects the latter over the former.”
>
>>   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 4070f9c17e8..91ab75aed06 100644
>> --- a/gcc/varasm.c
>> +++ b/gcc/varasm.c
>> @@ -726,12 +726,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);
>>   
>> @@ -744,12 +758,12 @@ 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.  */
>>         else if (DECL_COMDAT_GROUP (decl)
>> @@ -767,15 +781,18 @@ default_function_rodata_section (tree decl)
>>   	       && 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);
>>   	}
>>       }
> Don't we need to handle the .gnu.linkonce.t. case too?  I believe
> the suffix there is “.d.rel.ro.local” (replacing “.t”)
>
> My main concern is how this interacts with non-ELF targets.
> It looks like AIX/XCOFF, Darwin and Cygwin already pick
> default_no_function_rodata_section, so they should be fine.
> But at the moment, all the fancy stuff in default_function_rodata_section
> is indirectly guarded by targetm_common.have_named_sections, with the
> hook falling back to readonly_data_section if the function isn't in a
> named section.
>
> So I wonder if it would be safer to test targetm_common.have_named_sections
> in this condition:
>
>> +
>> +	      /* Judge if it's a absolute jump table. Set relocatable for
>> +		 absolute jump table if the target supports relocations.  */
>> +
>> +	      if (!CASE_VECTOR_PC_RELATIVE
>> +		  && !targetm.asm_out.generate_pic_addr_diff_vec ())
>> +		relocatable = targetm.asm_out.reloc_rw_mask ();
>>   
>>   	      switch_to_section (targetm.asm_out.function_rodata_section
>> -				 (current_function_decl));
>> +				 (current_function_decl, relocatable));
>>   
>>   #ifdef ADDR_VEC_ALIGN
>>   	      log_align = ADDR_VEC_ALIGN (table);
> Similarly for the other case where the condition appears.  I think the
> condition is subtle enough that it's worth splitting out into a helper.
>
> Thanks,
> Richard
* 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/rs6000/linux64.h (JUMP_TABLES_IN_TEXT_SECTION): Define.
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/rs6000/linux64.h b/gcc/config/rs6000/linux64.h
index 73b6c01874c..35038570e04 100644
--- a/gcc/config/rs6000/linux64.h
+++ b/gcc/config/rs6000/linux64.h
@@ -241,7 +241,7 @@ extern int dot_symbols;
 
 /* Indicate that jump tables go in the text section.  */
 #undef  JUMP_TABLES_IN_TEXT_SECTION
-#define JUMP_TABLES_IN_TEXT_SECTION TARGET_64BIT
+#define JUMP_TABLES_IN_TEXT_SECTION rs6000_relative_jumptables
 
 /* The linux ppc64 ABI isn't explicit on whether aggregates smaller
    than a doubleword should be padded upward or downward.  You could
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index dbb541bbea7..86978648299 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -11697,7 +11697,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 18edea1ce47..aaf41a559cc 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -11250,7 +11250,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 97437e8274f..d4fbd750fc7 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 eb253c50329..661ce9074ae 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -571,8 +571,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 ed2da154e30..d538cbbdf6b 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -549,16 +549,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 ea0b59cf44a..40502049b61 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -727,12 +727,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);
 
@@ -745,38 +759,57 @@ 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");
+	      strcat (rname, ".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
@@ -784,7 +817,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;
 }
@@ -794,7 +827,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
HAO CHEN GUI Nov. 6, 2020, 1:06 a.m. UTC | #4
Hi,

Gentle ping this:

https://gcc.gnu.org/pipermail/gcc-patches/2020-October/556744.html

Thanks

Gui Haochen


On 22/10/2020 上午 10:53, HAO CHEN GUI wrote:
> I had a wrong email setting and got your reply later. I modified the 
> patch according to your advice. Could you please review it again? Thanks.
>
> On 2/10/2020 上午 1:47, Richard Sandiford wrote:
>> Sorry for the slow review.
>>
>> HAO CHEN GUI via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
>>> diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
>>> index 513fc5fe295..6f5bf8d7d73 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 relocatable 
>>> ATTRIBUTE_UNUSED)
>> Now that we're C++, it's more idiomatic to leave off the parameter name:
>>
>>    mips_function_rodata_section (tree decl, bool)
>>
>> Same for the rest of the patch.
>>
>>> @@ -2491,9 +2491,19 @@ final_scan_insn_1 (rtx_insn *insn, FILE 
>>> *file, int optimize_p ATTRIBUTE_UNUSED,
>>>         if (! JUMP_TABLES_IN_TEXT_SECTION)
>>>           {
>>>             int log_align;
>>> +          bool relocatable;
>>> +
>>> +          relocatable = 0;
>> Very minor, but simpler as:
>>
>>     bool relocatable = false;
>>
>> Same for the later hunk.
>>
>>> @@ -549,16 +549,17 @@ 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 or relocated readonly data section
>>> +   associated with function DECL.  */
>>>   DEFHOOK
>>>   (function_rodata_section,
>>> - "Return the readonly data section associated with\n\
>>> + "Return the readonly or reloc readonly data section associated 
>>> with\n\
>>>   @samp{DECL_SECTION_NAME (@var{decl})}.\n\
>> Maybe add “; @var{relocatable} selects the latter over the former.”
>>
>>>   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 4070f9c17e8..91ab75aed06 100644
>>> --- a/gcc/varasm.c
>>> +++ b/gcc/varasm.c
>>> @@ -726,12 +726,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);
>>>   @@ -744,12 +758,12 @@ 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.  */
>>>         else if (DECL_COMDAT_GROUP (decl)
>>> @@ -767,15 +781,18 @@ default_function_rodata_section (tree decl)
>>>              && 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);
>>>       }
>>>       }
>> Don't we need to handle the .gnu.linkonce.t. case too?  I believe
>> the suffix there is “.d.rel.ro.local” (replacing “.t”)
>>
>> My main concern is how this interacts with non-ELF targets.
>> It looks like AIX/XCOFF, Darwin and Cygwin already pick
>> default_no_function_rodata_section, so they should be fine.
>> But at the moment, all the fancy stuff in 
>> default_function_rodata_section
>> is indirectly guarded by targetm_common.have_named_sections, with the
>> hook falling back to readonly_data_section if the function isn't in a
>> named section.
>>
>> So I wonder if it would be safer to test 
>> targetm_common.have_named_sections
>> in this condition:
>>
>>> +
>>> +          /* Judge if it's a absolute jump table. Set relocatable for
>>> +         absolute jump table if the target supports relocations.  */
>>> +
>>> +          if (!CASE_VECTOR_PC_RELATIVE
>>> +          && !targetm.asm_out.generate_pic_addr_diff_vec ())
>>> +        relocatable = targetm.asm_out.reloc_rw_mask ();
>>>               switch_to_section 
>>> (targetm.asm_out.function_rodata_section
>>> -                 (current_function_decl));
>>> +                 (current_function_decl, relocatable));
>>>     #ifdef ADDR_VEC_ALIGN
>>>             log_align = ADDR_VEC_ALIGN (table);
>> Similarly for the other case where the condition appears.  I think the
>> condition is subtle enough that it's worth splitting out into a helper.
>>
>> Thanks,
>> Richard
Richard Sandiford Nov. 13, 2020, 9:27 a.m. UTC | #5
Hi,

Sorry for the slow reply.  Just one minor nit:

HAO CHEN GUI <guihaoc@linux.ibm.com> writes:
> diff --git a/gcc/varasm.c b/gcc/varasm.c
> index ea0b59cf44a..40502049b61 100644
> --- a/gcc/varasm.c
> +++ b/gcc/varasm.c
> @@ -727,12 +727,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);
>  
> @@ -745,38 +759,57 @@ 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");
> +	      strcat (rname, ".rel.ro.local");
> +	      strcat (rname, name + 15);

I realise you probably wrote it like this to make the correlation
between the length calculation and the string operations more
obvious, but IMO it would be less surprising to have:

	      strcpy (rname, ".gnu.linkonce.d.rel.ro.local");

OK with that change, thanks.

Richard
HAO CHEN GUI Nov. 17, 2020, 5:57 a.m. UTC | #6
Hi,

I just tweaked the patch according to your advice and committed it. 
Thanks so much for your help and advice.

Haochen Gui

On 13/11/2020 下午 5:27, Richard Sandiford wrote:
> Hi,
>
> Sorry for the slow reply.  Just one minor nit:
>
> HAO CHEN GUI <guihaoc@linux.ibm.com> writes:
>> diff --git a/gcc/varasm.c b/gcc/varasm.c
>> index ea0b59cf44a..40502049b61 100644
>> --- a/gcc/varasm.c
>> +++ b/gcc/varasm.c
>> @@ -727,12 +727,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);
>>   
>> @@ -745,38 +759,57 @@ 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");
>> +	      strcat (rname, ".rel.ro.local");
>> +	      strcat (rname, name + 15);
> I realise you probably wrote it like this to make the correlation
> between the length calculation and the string operations more
> obvious, but IMO it would be less surprising to have:
>
> 	      strcpy (rname, ".gnu.linkonce.d.rel.ro.local");
>
> OK with that change, thanks.
>
> Richard
diff mbox series

Patch

diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 513fc5fe295..6f5bf8d7d73 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 relocatable ATTRIBUTE_UNUSED)
 {
   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/rs6000/linux64.h b/gcc/config/rs6000/linux64.h
index 34776c8421e..29d2d7ce40b 100644
--- a/gcc/config/rs6000/linux64.h
+++ b/gcc/config/rs6000/linux64.h
@@ -324,7 +324,7 @@  extern int dot_symbols;
 
 /* Indicate that jump tables go in the text section.  */
 #undef  JUMP_TABLES_IN_TEXT_SECTION
-#define JUMP_TABLES_IN_TEXT_SECTION TARGET_64BIT
+#define JUMP_TABLES_IN_TEXT_SECTION rs6000_relative_jumptables
 
 /* The linux ppc64 ABI isn't explicit on whether aggregates smaller
    than a doubleword should be padded upward or downward.  You could
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 758315c0c72..eb619d39ad7 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -11639,7 +11639,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 cd1c0634b71..6ca03ed9002 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -11218,7 +11218,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 6e7d9dc54a9..3907b7b8cc7 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -7703,13 +7703,13 @@  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
+@deftypefn {Target Hook} {section *} TARGET_ASM_FUNCTION_RODATA_SECTION (tree @var{decl}, bool @var{relocatable})
+Return the readonly or reloc readonly data section associated with
 @samp{DECL_SECTION_NAME (@var{decl})}.
 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 a3601964a8d..c86e639dc23 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -2491,9 +2491,19 @@  final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
 	  if (! JUMP_TABLES_IN_TEXT_SECTION)
 	    {
 	      int log_align;
+	      bool relocatable;
+
+	      relocatable = 0;
+
+	      /* Judge if it's a absolute jump table. Set relocatable for
+		 absolute jump table if the target supports relocations.  */
+
+	      if (!CASE_VECTOR_PC_RELATIVE
+		  && !targetm.asm_out.generate_pic_addr_diff_vec ())
+		relocatable = targetm.asm_out.reloc_rw_mask ();
 
 	      switch_to_section (targetm.asm_out.function_rodata_section
-				 (current_function_decl));
+				 (current_function_decl, relocatable));
 
 #ifdef ADDR_VEC_ALIGN
 	      log_align = ADDR_VEC_ALIGN (table);
@@ -2571,8 +2581,21 @@  final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
 #endif
 
 	    if (! JUMP_TABLES_IN_TEXT_SECTION)
-	      switch_to_section (targetm.asm_out.function_rodata_section
-				 (current_function_decl));
+	      {
+		bool relocatable;
+
+		relocatable = 0;
+
+		/* Judge if it's a absolute jump table. Set relocatable for
+		   absolute jump table if the target supports relocations.  */
+
+		if (!CASE_VECTOR_PC_RELATIVE
+		    && !targetm.asm_out.generate_pic_addr_diff_vec ())
+		   relocatable = targetm.asm_out.reloc_rw_mask ();
+
+		switch_to_section (targetm.asm_out.function_rodata_section
+				   (current_function_decl, relocatable));
+	      }
 	    else
 	      switch_to_section (current_function_section ());
 
diff --git a/gcc/output.h b/gcc/output.h
index eb253c50329..94eb0d6ebef 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -571,8 +571,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 relocatable);
+extern section *default_no_function_rodata_section (tree, bool relocatable);
 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 07059a87caf..8cda974c3c5 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -549,16 +549,17 @@  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 or relocated readonly data section
+   associated with function DECL.  */
 DEFHOOK
 (function_rodata_section,
- "Return the readonly data section associated with\n\
+ "Return the readonly or reloc readonly data section associated with\n\
 @samp{DECL_SECTION_NAME (@var{decl})}.\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 4070f9c17e8..91ab75aed06 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -726,12 +726,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);
 
@@ -744,12 +758,12 @@  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.  */
       else if (DECL_COMDAT_GROUP (decl)
@@ -767,15 +781,18 @@  default_function_rodata_section (tree decl)
 	       && 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
@@ -783,7 +800,8 @@  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 decl ATTRIBUTE_UNUSED,
+				    bool relocatable ATTRIBUTE_UNUSED)
 {
   return readonly_data_section;
 }
@@ -793,7 +811,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