This is the mail archive of the binutils@sources.redhat.com 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] Weak definition operrides strong definition


When linking a mixture of strong and weak symbols the attributes (size, type) 
of the resulting symbol is the size/type of the last symbol seen, not the 
strong definition. This breaks Arm interworking when linking an arm 
(STT_FUNC) weak definition and a thumb (STT_ARM_TFUNC) strong definition, and 
vice versa. If the weak definition appears after the strong definition the 
symbol is given the STT_FUNC, and the wrong interworking stubs are generated.

This bug could also cause problems with utilities that use the st_size field.

The attached files demonstrate the problem. Compile with gcc foo1.c foo2.c and 
the "foo" symbol will have the address of the smaller routine, but the size 
of the larger.

The attached patch fixes this by skipping weak definitions if we have already 
seen a non-weak definition.

Tested on i686-linux and arm-none-eabi.
Ok?

Paul

2005-05-01  Paul Brook  <paul@codesourcery.com>

	* elflink.c (_bfd_elf_merge_symbol): Skip weak definitions if a strong
	definition has already been seen.
void foo ()
{
}
int main()
{
  foo();
  return 0;
}

#include <stdio.h>
void __attribute__((weak))
foo()
{
  printf("Hello\n");
  printf("World\n");
}


Index: bfd/elflink.c
===================================================================
RCS file: /var/cvsroot/src-cvs/src/bfd/elflink.c,v
retrieving revision 1.136.2.1
diff -u -p -r1.136.2.1 elflink.c
--- bfd/elflink.c	22 Mar 2005 14:49:54 -0000	1.136.2.1
+++ bfd/elflink.c	1 May 2005 12:51:24 -0000
@@ -1075,6 +1075,10 @@ _bfd_elf_merge_symbol (bfd *abfd,
       || h->root.type == bfd_link_hash_undefined)
     *size_change_ok = TRUE;
 
+  /* Skip weak definitions of symbols that are already defined.  */
+  if (newdef && olddef && newweak && !oldweak)
+    *skip = TRUE;
+
   /* NEWDYNCOMMON and OLDDYNCOMMON indicate whether the new or old
      symbol, respectively, appears to be a common symbol in a dynamic
      object.  If a symbol appears in an uninitialized section, and is

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