File gcc7-pfe-0023-Backport-rs6000-Adjust-fpatchable-function-entry-sup.patch of Package gcc7

From a736805ca10cc7df9de97369938630e4dd67ebd6 Mon Sep 17 00:00:00 2001
From: Giuliano Belinassi <gbelinassi@suse.de>
Date: Thu, 25 Jul 2024 17:09:56 -0300
Subject: [PATCH] Backport rs6000: Adjust -fpatchable-function-entry* support
 for dual entry [PR112980]

As the discussion in PR112980, although the current
implementation for -fpatchable-function-entry* conforms
with the documentation (making N NOPs be consecutive),
it's inefficient for both kernel and userspace livepatching
(see comments in PR for the details).

So this patch is to change the current implementation by
emitting the "before" NOPs before global entry point and
the "after" NOPs after local entry point.  The new behavior
would not keep NOPs to be consecutive, so the documentation
is updated to emphasize this.

Authored-by: Kewen Lin <linkw@linux.ibm.com>
Backported-by: Giuliano Belinassi <gbelinassi@suse.de>

Signed-off-by: Giuliano Belinassi <gbelinassi@suse.de>
---
 gcc/config/rs6000/rs6000.c | 42 +++++++++++++++++++++++++++++---------
 1 file changed, 32 insertions(+), 10 deletions(-)

diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index d0e3ba29c7d..0df48d1f673 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -159,6 +159,12 @@ typedef struct GTY(()) machine_function
      not be considered by the prologue and epilogue.  */
   bool gpr_is_wrapped_separately[32];
   bool lr_is_wrapped_separately;
+  /* With ELFv2 ABI dual entry points being adopted, generic framework
+     targetm.asm_out.print_patchable_function_entry would generate "after"
+     NOPs before local entry, it is wrong.  This flag is to stop it from
+     printing patch area before local entry, it is only useful when the
+     function requires dual entry points.  */
+  bool stop_patch_area_print;
 } machine_function;
 
 /* Support targetm.vectorize.builtin_mask_for_load.  */
@@ -24451,6 +24457,9 @@ rs6000_assemble_visibility (tree decl, int vis)
 }
 #endif
 
+
+static bool rs6000_global_entry_point_needed_p (void);
+
 /* Write PATCH_AREA_SIZE NOPs into the asm outfile FILE around a function
    entry.  If RECORD_P is true and the target supports named sections,
    the location of the NOPs will be recorded in a special object section
@@ -24463,16 +24472,15 @@ rs6000_print_patchable_function_entry (FILE *file,
 				       unsigned HOST_WIDE_INT patch_area_size,
 				       bool record_p)
 {
-  unsigned int flags = SECTION_WRITE | SECTION_RELRO;
-  /* When .opd section is emitted, the function symbol
-     default_print_patchable_function_entry_1 is emitted into the .opd section
-     while the patchable area is emitted into the function section.
-     Don't use SECTION_LINK_ORDER in that case.  */
-  if (!(TARGET_64BIT && DEFAULT_ABI != ABI_ELFv2)
-      && HAVE_GAS_SECTION_LINK_ORDER)
-    flags |= SECTION_LINK_ORDER;
-  default_print_patchable_function_entry_1 (file, patch_area_size, record_p,
-					    flags);
+  bool global_entry_needed_p = rs6000_global_entry_point_needed_p ();
+  /* For a function which needs global entry point, we will only emit the
+     patchable area after local entry point under the control of
+     !cfun->machine->stop_patch_area_print, see the handling in functions
+     rs6000_output_function_prologue.  */
+  if (!cfun->machine->stop_patch_area_print)
+    default_print_patchable_function_entry (file, patch_area_size, record_p);
+  else
+    gcc_assert (global_entry_needed_p);
 }
 
 
@@ -30590,6 +30598,18 @@ rs6000_output_function_prologue (FILE *file,
       fputs (",.-", file);
       assemble_name (file, name);
       fputs ("\n", file);
+
+      /* Emit the nops after local entry.  */
+      unsigned short patch_area_size = crtl->patch_area_size;
+      unsigned short patch_area_entry = crtl->patch_area_entry;
+      if (patch_area_size > patch_area_entry)
+	{
+	  cfun->machine->stop_patch_area_print = false;
+	  patch_area_size -= patch_area_entry;
+	  rs6000_print_patchable_function_entry (file, patch_area_size,
+						 patch_area_entry == 0);
+	}
+
     }
 
   /* Output -mprofile-kernel code.  This needs to be done here instead of
@@ -36446,6 +36466,8 @@ rs6000_elf_declare_function_name (FILE *file, const char *name, tree decl)
       fprintf (file, "\t.previous\n");
     }
   ASM_OUTPUT_LABEL (file, name);
+  if (rs6000_global_entry_point_needed_p())
+    cfun->machine->stop_patch_area_print = true;
 }
 
 static void rs6000_elf_file_end (void) ATTRIBUTE_UNUSED;
-- 
2.45.2

openSUSE Build Service is sponsored by