This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH: PR ld/6877: Inconsistent treatment of common and text


We are supposed to allow a common symbol to override the function in a
shared library. But it only works if the commom symbol comes first.
This patch fixes it.  OK to install?

Thanks.


H.J.
---
bfd/

2008-09-10  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/6877
	* elflink.c (_bfd_elf_merge_symbol): Allow a common symbol to
	override the function in a shared library.

ld/testsuite/

2008-09-10  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/6877
	* ld-elf/comm1.c: New.
	* ld-elf/func1.c: Likewise.

	* ld-elf/shared.exp: Add tests for libfunc1.so and comm1.

--- binutils/bfd/elflink.c.func	2008-09-10 10:10:18.000000000 -0700
+++ binutils/bfd/elflink.c	2008-09-10 18:00:11.000000000 -0700
@@ -903,7 +903,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
   int bind;
   bfd *oldbfd;
   bfd_boolean newdyn, olddyn, olddef, newdef, newdyncommon, olddyncommon;
-  bfd_boolean newweak, oldweak;
+  bfd_boolean newweak, oldweak, newfunc, oldfunc;
   const struct elf_backend_data *bed;
 
   *skip = FALSE;
@@ -1022,6 +1022,15 @@ _bfd_elf_merge_symbol (bfd *abfd,
 	    && h->root.type != bfd_link_hash_undefweak
 	    && h->root.type != bfd_link_hash_common);
 
+  /* NEWFUNC and OLDFUNC indicate whether the new or old symbol,
+     respectively, appear to be a function.  */
+
+  newfunc = (ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
+	     && bed->is_function_type (ELF_ST_TYPE (sym->st_info)));
+
+  oldfunc = (h->type != STT_NOTYPE
+	     && bed->is_function_type (h->type));
+
   /* When we try to create a default indirect symbol from the dynamic
      definition with the default version, we skip it if its type and
      the type of existing regular definition mismatch.  We only do it
@@ -1037,8 +1046,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
       && ELF_ST_TYPE (sym->st_info) != h->type
       && ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
       && h->type != STT_NOTYPE
-      && !(bed->is_function_type (ELF_ST_TYPE (sym->st_info))
-	   && bed->is_function_type (h->type)))
+      && !(newfunc && oldfunc))
     {
       *skip = TRUE;
       return TRUE;
@@ -1219,8 +1227,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
     oldweak = FALSE;
 
   /* Allow changes between different types of funciton symbol.  */
-  if (bed->is_function_type (ELF_ST_TYPE (sym->st_info))
-      && bed->is_function_type (h->type))
+  if (newfunc && oldfunc)
     *type_change_ok = TRUE;
 
   /* It's OK to change the type if either the existing symbol or the
@@ -1269,7 +1276,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
       && (sec->flags & SEC_ALLOC) != 0
       && (sec->flags & SEC_LOAD) == 0
       && sym->st_size > 0
-      && !bed->is_function_type (ELF_ST_TYPE (sym->st_info)))
+      && !newfunc)
     newdyncommon = TRUE;
   else
     newdyncommon = FALSE;
@@ -1281,7 +1288,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
       && (h->root.u.def.section->flags & SEC_ALLOC) != 0
       && (h->root.u.def.section->flags & SEC_LOAD) == 0
       && h->size > 0
-      && !bed->is_function_type (h->type))
+      && !oldfunc)
     olddyncommon = TRUE;
   else
     olddyncommon = FALSE;
@@ -1341,8 +1348,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
       && newdef
       && (olddef
 	  || (h->root.type == bfd_link_hash_common
-	      && (newweak
-		  || bed->is_function_type (ELF_ST_TYPE (sym->st_info))))))
+	      && (newweak || newfunc))))
     {
       *override = TRUE;
       newdef = FALSE;
@@ -1396,8 +1402,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
   if (!newdyn
       && (newdef
 	  || (bfd_is_com_section (sec)
-	      && (oldweak
-		  || bed->is_function_type (h->type))))
+	      && (oldweak || oldfunc)))
       && olddyn
       && olddef
       && h->def_dynamic)
@@ -1417,7 +1422,17 @@ _bfd_elf_merge_symbol (bfd *abfd,
 	 overriding a function.  */
 
       if (bfd_is_com_section (sec))
-	*type_change_ok = TRUE;
+	{
+	  if (oldfunc)
+	    {
+	      /* If a common symbol overrides a function, make sure
+		 that it isn't defined dynamically nor has type
+		 function.  */
+	      h->def_dynamic = 0;
+	      h->type = STT_NOTYPE;
+	    }
+	  *type_change_ok = TRUE;
+	}
 
       if ((*sym_hash)->root.type == bfd_link_hash_indirect)
 	flip = *sym_hash;
--- binutils/ld/testsuite/ld-elf/comm1.c.func	2008-09-10 18:00:32.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/comm1.c	2008-09-10 17:54:56.000000000 -0700
@@ -0,0 +1,17 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+int foo;
+void bar (void);
+
+int
+main ()
+{
+  if (foo != 0)
+    abort ();
+  foo = 200; 
+  bar ();
+  if (foo == 200)
+    printf ("PASS\n");
+  return 0;
+}
--- binutils/ld/testsuite/ld-elf/func1.c.func	2008-09-10 18:00:32.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/func1.c	2008-09-10 17:55:08.000000000 -0700
@@ -0,0 +1,2 @@
+void foo (void) { }
+void bar (void) { }
--- binutils/ld/testsuite/ld-elf/shared.exp.func	2008-09-10 10:10:18.000000000 -0700
+++ binutils/ld/testsuite/ld-elf/shared.exp	2008-09-10 17:59:54.000000000 -0700
@@ -126,6 +126,9 @@ set build_tests {
   {"Build libdata2.so"
    "-shared" "-fPIC"
    {data2.c} {} "libdata2.so"}
+  {"Build libfunc1.so"
+   "-shared" "-fPIC"
+   {func1.c} {} "libfunc1.so"}
 }
 
 set run_tests {
@@ -241,6 +244,12 @@ set run_tests {
     {"Run with libdata2.so"
      "tmpdir/libdata2.so" ""
      {weakdef1.c} "weakdef1" "pass.out"}
+    {"Run with libfunc1.so comm1.o"
+     "tmpdir/libfunc1.so tmpdir/comm1.o" ""
+     {dummy.c} "comm1" "pass.out"}
+    {"Run with comm1.o libfunc1.so"
+     "tmpdir/comm1.o tmpdir/libfunc1.so" ""
+     {dummy.c} "comm1" "pass.out"}
 }
 
 run_cc_link_tests $build_tests


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