This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Handle weak symbols
- To: gcc-patches at gcc dot gnu dot org
- Subject: [PATCH] Handle weak symbols
- From: Franz Sirl <Franz dot Sirl-kernel at lauterbach dot com>
- Date: Sun, 6 May 2001 21:25:23 +0200
Hi,
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?
Franz.
* 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 (
#ifdef ASM_WEAKEN_LABEL
static void remove_from_pending_weak_list PARAMS ((const char *));
#endif
+static int is_on_pending_weak_list PARAMS ((const char *));
#ifdef ASM_OUTPUT_BSS
static void asm_output_bss PARAMS ((FILE *, tree, const char *, int, int));
#endif
@@ -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");
+#endif
else if (SUPPORTS_WEAK)
DECL_WEAK (decl) = 1;
#ifdef HANDLE_PRAGMA_WEAK
@@ -4795,6 +4803,24 @@ remove_from_pending_weak_list (name)
#endif
}
#endif
+
+static int
+is_on_pending_weak_list (name)
+ const char *name ATTRIBUTE_UNUSED;
+{
+#ifdef HANDLE_PRAGMA_WEAK
+ if (HANDLE_PRAGMA_WEAK)
+ {
+ struct weak_syms *t;
+ for (t = weak_decls; t; t = t->next)
+ {
+ if (t->name && strcmp (name, t->name) == 0)
+ return 1;
+ }
+ }
+#endif
+ return 0;
+}
void
assemble_alias (decl, target)