This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[PATCH] Handle weak symbols


this is the long promised patch to handle weak symbol references in gcc 
better to prevent miscompilations. This was triggered by a change in glibc 
which exposed the possible miscompilation.

To fix the bug I'm mirroring the DECL_WEAK flag into the RTL in 
make_decl_rtl. Then I'm checking the new flag in rtx_addr_can_trap_p and 
reject weak SYMBOL_REFs.
The error checks in declare_weak were never active in practice, cause 
duplicate_decls was not using this routine, I fixed that as well. 
Unfortunately this exposed a bug in this error checking, so I had to disable  
one of them to be able to compile glibc.

Note that this patch only *disables* certain optimizations possible without 
it, so that the disabled error check isn't a regression from previous 
behaviour. But there are other place in gcc where possible optimizations 
aren't currently done, so enabling these optimizations would require proper 
error and warning checks.

I've tested that the patch bootstraps on powerpc-linux-gnu and x86-linux-gnu 
without regressions and I've compiled (and used) glibc and nearly all 
packages on my local system without a problem.

Since it affects glibc, I would like to apply the patch to mainline and 
branch, OK?


	* rtl.h (SYMBOL_REF_WEAK): New macro.
	* rtlanal.h (rtx_addr_can_trap): Use it, a weak SYMBOL_REF can trap.
	* varasm.c (make_decl_rtl): Mark DECL weak if we have seen a #pragma
	weak for the symbolname. Copy the weak status into the SYMBOL_REF.
	(is_on_pending_weak_list): New function.
	* c-decl.c (duplicate_decls): Use declare_weak to mark a DECL weak.

Index: gcc/c-decl.c
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.220
diff -u -p -r1.220 c-decl.c
--- gcc/c-decl.c	2001/05/01 12:11:31	1.220
+++ gcc/c-decl.c	2001/05/06 09:20:31
@@ -1922,8 +1922,12 @@ duplicate_decls (newdecl, olddecl, diffe
       TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
-  /* Merge the storage class information.  */
-  DECL_WEAK (newdecl) |= DECL_WEAK (olddecl);
+  /* Merge the storage class information. declare_weak gets us
+     all the error checking.  */
+  if (DECL_WEAK (olddecl) && !DECL_WEAK (newdecl))
+    declare_weak (newdecl);
+  if (DECL_WEAK (newdecl) && !DECL_WEAK (olddecl))
+    declare_weak (olddecl);
   /* For functions, static overrides non-static.  */
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
Index: gcc/rtl.h
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.257
diff -u -p -r1.257 rtl.h
--- gcc/rtl.h	2001/04/28 19:16:29	1.257
+++ gcc/rtl.h	2001/05/06 09:20:33
@@ -162,7 +162,8 @@ typedef struct rtx_def
   unsigned int used : 1;
   /* Nonzero if this rtx came from procedure integration.
      In a REG, nonzero means this reg refers to the return value
-     of the current function.  */
+     of the current function.
+     1 in a SYMBOL_REF if the symbol is weak.  */
   unsigned integrated : 1;
   /* 1 in an INSN or a SET if this rtx is related to the call frame,
      either changing how we compute the frame address or saving and
@@ -933,6 +934,9 @@ extern unsigned int subreg_regno 	PARAMS
 /* 1 means a SYMBOL_REF has been the library function in emit_library_call.  */
 #define SYMBOL_REF_USED(RTX) ((RTX)->used)
+/* 1 means a SYMBOL_REF is weak.  */
+#define SYMBOL_REF_WEAK(RTX) ((RTX)->integrated)
 /* Define a macro to look for REG_INC notes,
    but save time on machines where they never exist.  */
Index: gcc/varasm.c
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.173
diff -u -p -r1.173 varasm.c
--- gcc/varasm.c	2001/05/01 12:11:34	1.173
+++ gcc/varasm.c	2001/05/06 09:20:35
@@ -168,6 +168,7 @@ static void output_constructor		PARAMS (
 static void remove_from_pending_weak_list	PARAMS ((const char *));
+static int is_on_pending_weak_list	PARAMS ((const char *));
 static void asm_output_bss		PARAMS ((FILE *, tree, const char *, int, int));
@@ -747,6 +748,9 @@ make_decl_rtl (decl, asmspec)
   SET_DECL_RTL (decl, gen_rtx_MEM (DECL_MODE (decl),
 				   gen_rtx_SYMBOL_REF (Pmode, name)));
+  if (is_on_pending_weak_list (name))
+    declare_weak (decl);
+  SYMBOL_REF_WEAK (XEXP (DECL_RTL (decl), 0)) = DECL_WEAK (decl);
   if (TREE_CODE (decl) != FUNCTION_DECL)
     set_mem_attributes (DECL_RTL (decl), decl, 1);
@@ -4739,8 +4743,12 @@ declare_weak (decl)
   if (! TREE_PUBLIC (decl))
     error_with_decl (decl, "weak declaration of `%s' must be public");
+#if 0
+  /* Due to a bug this error was never active, allowing it now would break
+     glibc compile.  */
   else if (TREE_ASM_WRITTEN (decl))
     error_with_decl (decl, "weak declaration of `%s' must precede definition");
   else if (SUPPORTS_WEAK)
     DECL_WEAK (decl) = 1;
@@ -4795,6 +4803,24 @@ remove_from_pending_weak_list (name)
+static int
+is_on_pending_weak_list (name)
+     const char *name ATTRIBUTE_UNUSED;
+    {
+      struct weak_syms *t;
+      for (t = weak_decls; t; t = t->next)
+	{
+	  if (t->name && strcmp (name, t->name) == 0)
+	    return 1;
+	}
+    }
+  return 0;
 assemble_alias (decl, target)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]