PATCH: target/19520: protected function pointer doesn't work right

H. J. Lu hjl@lucon.org
Thu Jan 20 22:57:00 GMT 2005


The issue is the function address of a protected function isn't
necessarily the same as the address of the function body nor has to
be in the same DSO where the function is defined. In that case, the
only optimization we can do is to skip PLT when branch. This
patch marks if a symbol is protected and also treats a protected
function as normal. But it will skip PLT when generating the branch
instruction.


H.J.
----
2005-01-20  H.J. Lu  <hongjiu.lu@intel.com>

	PR target/19520
	* config/i386/i386.c (output_pic_addr_const): Don't use PLT if
	a function is protected.

	* config/i386/linux.h (TARGET_BINDS_LOCAL_P): Defined.
	* config/i386/linux64.h (TARGET_BINDS_LOCAL_P): Likewise.

	* output.h (default_binds_exclude_protected_local_p): New.
	(default_binds_exclude_protected_local_p_1): Likewise.

	* rtl.h (SYMBOL_FLAG_PROTECTED): New.
	(SYMBOL_REF_PROTECTED_P): Likewise.

	* varasm.c (default_encode_section_info): Check and set
	SYMBOL_FLAG_PROTECTED.
	(default_binds_exclude_protected_local_p): New.
	(default_binds_exclude_protected_local_p_1): Likewise.

--- gcc/config/i386/i386.c.vsb	2005-01-20 11:30:01.000000000 -0800
+++ gcc/config/i386/i386.c	2005-01-20 14:40:28.000000000 -0800
@@ -5881,7 +5881,9 @@ output_pic_addr_const (FILE *file, rtx x
        mark_decl_referenced (SYMBOL_REF_DECL (x));
 
       assemble_name (file, XSTR (x, 0));
-      if (!TARGET_MACHO && code == 'P' && ! SYMBOL_REF_LOCAL_P (x))
+      if (!TARGET_MACHO && code == 'P'
+	  && ! SYMBOL_REF_LOCAL_P (x)
+	  && ! SYMBOL_REF_PROTECTED_P (x))
 	fputs ("@PLT", file);
       break;
 
--- gcc/config/i386/linux.h.vsb	2004-11-27 08:45:14.000000000 -0800
+++ gcc/config/i386/linux.h	2005-01-20 13:57:37.000000000 -0800
@@ -25,6 +25,8 @@ Boston, MA 02111-1307, USA.  */
 /* The .file command should always begin the output.  */
 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
 
+#define TARGET_BINDS_LOCAL_P default_binds_exclude_protected_local_p
+
 #define TARGET_VERSION fprintf (stderr, " (i386 Linux/ELF)");
 
 /* The svr4 ABI for the i386 says that records and unions are returned
--- gcc/config/i386/linux64.h.vsb	2004-11-27 14:29:34.000000000 -0800
+++ gcc/config/i386/linux64.h	2005-01-20 13:57:15.000000000 -0800
@@ -19,6 +19,8 @@ along with GCC; see the file COPYING.  I
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
+#define TARGET_BINDS_LOCAL_P default_binds_exclude_protected_local_p
+
 #define TARGET_VERSION fprintf (stderr, " (x86-64 Linux/ELF)");
 
 #define TARGET_OS_CPP_BUILTINS()				\
--- gcc/output.h.vsb	2005-01-20 11:29:23.000000000 -0800
+++ gcc/output.h	2005-01-20 13:50:34.000000000 -0800
@@ -510,6 +510,8 @@ extern void default_encode_section_info 
 extern const char *default_strip_name_encoding (const char *);
 extern bool default_binds_local_p (tree);
 extern bool default_binds_local_p_1 (tree, int);
+extern bool default_binds_exclude_protected_local_p (tree);
+extern bool default_binds_exclude_protected_local_p_1 (tree, int);
 extern void default_globalize_label (FILE *, const char *);
 extern void default_emit_unwind_label (FILE *, tree, int, int);
 extern void default_internal_label (FILE *, const char *, unsigned long);
--- gcc/rtl.h.vsb	2005-01-20 11:29:24.000000000 -0800
+++ gcc/rtl.h	2005-01-20 13:33:42.000000000 -0800
@@ -1234,6 +1234,11 @@ do {						\
 #define SYMBOL_FLAG_MACH_DEP_SHIFT	7
 #define SYMBOL_FLAG_MACH_DEP		(1 << SYMBOL_FLAG_MACH_DEP_SHIFT)
 
+/* Set if this symbol is protected.  */
+#define SYMBOL_FLAG_PROTECTED	(1 << 8)
+#define SYMBOL_REF_PROTECTED_P(RTX) \
+  ((SYMBOL_REF_FLAGS (RTX) & SYMBOL_FLAG_PROTECTED) != 0)
+
 /* Define a macro to look for REG_INC notes,
    but save time on machines where they never exist.  */
 
--- gcc/varasm.c.vsb	2005-01-20 11:29:29.000000000 -0800
+++ gcc/varasm.c	2005-01-20 14:30:21.000000000 -0800
@@ -5203,6 +5203,8 @@ default_encode_section_info (tree decl, 
   flags = 0;
   if (TREE_CODE (decl) == FUNCTION_DECL)
     flags |= SYMBOL_FLAG_FUNCTION;
+  if (DECL_VISIBILITY (decl) == VISIBILITY_PROTECTED)
+    flags |= SYMBOL_FLAG_PROTECTED;
   if (targetm.binds_local_p (decl))
     flags |= SYMBOL_FLAG_LOCAL;
   if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
@@ -5277,6 +5279,65 @@ default_binds_local_p_1 (tree exp, int s
   return local_p;
 }
 
+/* Similar to default_binds_local_p, except for treating
+   protected function as normal.  */
+
+bool
+default_binds_exclude_protected_local_p (tree exp)
+{
+  return default_binds_exclude_protected_local_p_1 (exp, flag_shlib);
+}
+
+bool
+default_binds_exclude_protected_local_p_1 (tree exp, int shlib)
+{
+  bool local_p;
+
+  /* A non-decl is an entry in the constant pool.  */
+  if (!DECL_P (exp))
+    local_p = true;
+  /* Static variables are always local.  */
+  else if (! TREE_PUBLIC (exp))
+    local_p = true;
+  /* A variable is local if the user explicitly tells us so, excluding
+     protected function.  */
+  else if (DECL_VISIBILITY_SPECIFIED (exp)
+	   && ((DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT
+		&& DECL_VISIBILITY (exp) != VISIBILITY_PROTECTED)
+	       || ((!shlib || TREE_CODE (exp) != FUNCTION_DECL)
+		   && DECL_VISIBILITY (exp) == VISIBILITY_PROTECTED)))
+    local_p = true;
+  /* Otherwise, variables defined outside this object may not be local.  */
+  else if (DECL_EXTERNAL (exp))
+    local_p = false;
+  /* Linkonce and weak data are never local.  */
+  else if (DECL_ONE_ONLY (exp) || DECL_WEAK (exp))
+    local_p = false;
+  /* If none of the above and visibility is not default nor protected
+     function, make local.  */
+  else if ((DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT
+	    && DECL_VISIBILITY (exp) != VISIBILITY_PROTECTED)
+	   || ((!shlib || TREE_CODE (exp) != FUNCTION_DECL)
+	       && DECL_VISIBILITY (exp) == VISIBILITY_PROTECTED))
+    local_p = true;
+  /* If PIC, then assume that any global name can be overridden by
+     symbols resolved from other modules.  */
+  else if (shlib)
+    local_p = false;
+  /* Uninitialized COMMON variable may be unified with symbols
+     resolved from other modules.  */
+  else if (DECL_COMMON (exp)
+	   && (DECL_INITIAL (exp) == NULL
+	       || DECL_INITIAL (exp) == error_mark_node))
+    local_p = false;
+  /* Otherwise we're left with initialized (or non-common) global data
+     which is of necessity defined locally.  */
+  else
+    local_p = true;
+
+  return local_p;
+}
+
 /* Determine whether or not a pointer mode is valid. Assume defaults
    of ptr_mode or Pmode - can be overridden.  */
 bool



More information about the Gcc-patches mailing list