public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* PATCH: Fix alignment of common symbol
@ 2003-04-10 18:26 H. J. Lu
  2003-04-11 16:08 ` H. J. Lu
  0 siblings, 1 reply; 5+ messages in thread
From: H. J. Lu @ 2003-04-10 18:26 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 515 bytes --]

When there is a alignment differnce between common/normal symbols or
common symbols, ld doesn't check alignment. Here is a testcase:

gcc -O -g -c main.c
gcc -O -g -c foo.c
gcc -o foo1 -B./ main.o foo.o
/usr/bin/ld: Warning: size of symbol `foo' changed from 2 to 21 in foo.o
gcc -o foo2 -B./ foo.o main.o
for f in foo1 foo2; do echo "Running: $f"; ./$f; \
  if [ $? != 0 ]; then echo Failed; fi; done
Running: foo1
0x8049421: 1
0x8049536: 2
Running: foo2
0x8049421: 1
0x8049550: 16

I also include a patch.


H.J.

[-- Attachment #2: bfd-common.patch --]
[-- Type: text/plain, Size: 2047 bytes --]

2003-04-10  H.J. Lu <hjl@gnu.org>

	* elflink.h (elf_link_add_object_symbols): Properly handle
	alignment for common symbols.

--- bfd/elflink.h.common	2003-04-08 10:56:49.000000000 -0700
+++ bfd/elflink.h	2003-04-10 11:14:24.000000000 -0700
@@ -1999,6 +1999,8 @@ elf_link_add_object_symbols (abfd, info)
 		 is specified and no other alignments have been specified.  */
 	      || (isym->st_value == 1 && old_alignment == 0))
 	    h->root.u.c.p->alignment_power = align;
+	  else
+	    h->root.u.c.p->alignment_power = old_alignment;
 	}
 
       if (info->hash->creator->flavour == bfd_target_elf_flavour)
@@ -2007,6 +2009,42 @@ elf_link_add_object_symbols (abfd, info)
 	  bfd_boolean dynsym;
 	  int new_flag;
 
+	  /* Check the alignment when a common symbol is involved. It
+	     can happen when a common symbol is overriden by a normal
+	     definition or a common symbol is ignored due to the old
+	     normal definition. We need to make sure the maximum
+	     alignment is maintained.  */
+	  if ((old_alignment || isym->st_shndx == SHN_COMMON)
+	      && h->root.type != bfd_link_hash_common)
+	    {
+	      unsigned int common_align, normal_align, symbol_align;
+	      
+	      symbol_align = ffs (h->root.u.def.value) - 1;
+	      if ((h->root.u.def.section->owner->flags & DYNAMIC) == 0)
+		{
+		  normal_align = h->root.u.def.section->alignment_power;
+		  if (normal_align > symbol_align)
+		    normal_align = symbol_align;
+		}
+	      else
+		normal_align = symbol_align;
+
+	      if (old_alignment)
+		common_align = old_alignment;
+	      else
+		common_align = bfd_log2 (isym->st_value);
+
+	      if (normal_align < common_align)
+		{
+		  (*_bfd_error_handler)
+		    (_("alignment of symbol `%s' changed from %u to %u in %s"),
+		     name, 1 << common_align, 1 << normal_align,
+		     bfd_archive_filename (abfd));
+		  bfd_set_error (bfd_error_bad_value);
+		  goto error_free_vers;
+		}
+	    }
+
 	  /* Remember the symbol size and type.  */
 	  if (isym->st_size != 0
 	      && (definition || h->size == 0))

[-- Attachment #3: bug.tar.gz --]
[-- Type: application/x-gzip, Size: 662 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH: Fix alignment of common symbol
  2003-04-10 18:26 PATCH: Fix alignment of common symbol H. J. Lu
@ 2003-04-11 16:08 ` H. J. Lu
  2003-04-14 11:07   ` Nick Clifton
  0 siblings, 1 reply; 5+ messages in thread
From: H. J. Lu @ 2003-04-11 16:08 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 740 bytes --]

On Thu, Apr 10, 2003 at 11:26:14AM -0700, H. J. Lu wrote:
> When there is a alignment differnce between common/normal symbols or
> common symbols, ld doesn't check alignment. Here is a testcase:
> 
> gcc -O -g -c main.c
> gcc -O -g -c foo.c
> gcc -o foo1 -B./ main.o foo.o
> /usr/bin/ld: Warning: size of symbol `foo' changed from 2 to 21 in foo.o
> gcc -o foo2 -B./ foo.o main.o
> for f in foo1 foo2; do echo "Running: $f"; ./$f; \
>   if [ $? != 0 ]; then echo Failed; fi; done
> Running: foo1
> 0x8049421: 1
> 0x8049536: 2
> Running: foo2
> 0x8049421: 1
> 0x8049550: 16
> 
> I also include a patch.
> 

I took a look at Sun's linker doc. It says alignment change will
generate a warning, not a fatal error. Here is the new patch.


H.J.

[-- Attachment #2: bfd-common.patch --]
[-- Type: text/plain, Size: 4039 bytes --]

2003-04-11  H.J. Lu <hjl@gnu.org>

	* elflink.h (elf_link_add_object_symbols): Maintain maximum
	alignment for common symbols. Warn reducing alignment for
	common symbols. Report old filename when symbol size changes.

--- bfd/elflink.h.common	2003-04-10 16:22:43.000000000 -0700
+++ bfd/elflink.h	2003-04-11 08:58:53.000000000 -0700
@@ -1714,6 +1714,7 @@ elf_link_add_object_symbols (abfd, info)
       bfd_boolean new_weakdef;
       unsigned int old_alignment;
       bfd_boolean override;
+      bfd *old_bfd;
 
       override = FALSE;
 
@@ -1818,6 +1819,7 @@ elf_link_add_object_symbols (abfd, info)
       size_change_ok = FALSE;
       type_change_ok = get_elf_backend_data (abfd)->type_change_ok;
       old_alignment = 0;
+      old_bfd = NULL;
       if (info->hash->creator->flavour == bfd_target_elf_flavour)
 	{
 	  Elf_Internal_Versym iver;
@@ -1940,9 +1942,23 @@ elf_link_add_object_symbols (abfd, info)
 	     that we don't reduce the alignment later on.  We can't
 	     check later, because _bfd_generic_link_add_one_symbol
 	     will set a default for the alignment which we want to
-	     override.  */
-	  if (h->root.type == bfd_link_hash_common)
-	    old_alignment = h->root.u.c.p->alignment_power;
+	     override. We also remember the old bfd where the existing
+	     definition comes from.  */
+	  switch (h->root.type)
+	    {
+	    default:
+	      break;
+
+	    case bfd_link_hash_defined:
+	    case bfd_link_hash_defweak:
+	      old_bfd = h->root.u.def.section->owner;
+	      break;
+	    
+	    case bfd_link_hash_common:
+	      old_bfd = h->root.u.c.p->section->owner;
+	      old_alignment = h->root.u.c.p->alignment_power;
+	      break;
+	    }
 
 	  if (elf_tdata (abfd)->verdef != NULL
 	      && ! override
@@ -1999,6 +2015,8 @@ elf_link_add_object_symbols (abfd, info)
 		 is specified and no other alignments have been specified.  */
 	      || (isym->st_value == 1 && old_alignment == 0))
 	    h->root.u.c.p->alignment_power = align;
+	  else
+	    h->root.u.c.p->alignment_power = old_alignment;
 	}
 
       if (info->hash->creator->flavour == bfd_target_elf_flavour)
@@ -2007,15 +2025,50 @@ elf_link_add_object_symbols (abfd, info)
 	  bfd_boolean dynsym;
 	  int new_flag;
 
+	  /* Check the alignment when a common symbol is involved. It
+	     can happen when a common symbol is overriden by a normal
+	     definition or a common symbol is ignored due to the old
+	     normal definition. We need to make sure the maximum
+	     alignment is maintained.  */
+	  if ((old_alignment || isym->st_shndx == SHN_COMMON)
+	      && h->root.type != bfd_link_hash_common)
+	    {
+	      unsigned int common_align, normal_align, symbol_align;
+	      
+	      symbol_align = ffs (h->root.u.def.value) - 1;
+	      if ((h->root.u.def.section->owner->flags & DYNAMIC) == 0)
+		{
+		  normal_align = h->root.u.def.section->alignment_power;
+		  if (normal_align > symbol_align)
+		    normal_align = symbol_align;
+		}
+	      else
+		normal_align = symbol_align;
+
+	      if (old_alignment)
+		common_align = old_alignment;
+	      else
+		common_align = bfd_log2 (isym->st_value);
+
+	      if (normal_align < common_align)
+		(*_bfd_error_handler)
+		  (_("Warning: alignment %u of symbol `%s' in %s is smaller than %u in %s"),
+		   1 << normal_align, name,
+		   bfd_archive_filename (old_bfd),
+		   1 << common_align, bfd_archive_filename (abfd));
+	    }
+
 	  /* Remember the symbol size and type.  */
 	  if (isym->st_size != 0
 	      && (definition || h->size == 0))
 	    {
 	      if (h->size != 0 && h->size != isym->st_size && ! size_change_ok)
 		(*_bfd_error_handler)
-		  (_("Warning: size of symbol `%s' changed from %lu to %lu in %s"),
+		  (_("Warning: size of symbol `%s' changed from %lu in %s to %lu in %s"),
 		   name, (unsigned long) h->size,
-		   (unsigned long) isym->st_size, bfd_archive_filename (abfd));
+		   bfd_archive_filename (old_bfd),
+		   (unsigned long) isym->st_size,
+		   bfd_archive_filename (abfd));
 
 	      h->size = isym->st_size;
 	    }

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH: Fix alignment of common symbol
  2003-04-11 16:08 ` H. J. Lu
@ 2003-04-14 11:07   ` Nick Clifton
  2003-04-14 19:33     ` H. J. Lu
  0 siblings, 1 reply; 5+ messages in thread
From: Nick Clifton @ 2003-04-14 11:07 UTC (permalink / raw)
  To: H. J. Lu; +Cc: binutils

Hi H.J.

  Thanks for catching this.  Do you think that it is worth developing
  a linker test case to check for this ?

> 2003-04-11  H.J. Lu <hjl@gnu.org>
> 
> 	* elflink.h (elf_link_add_object_symbols): Maintain maximum
> 	alignment for common symbols. Warn reducing alignment for
> 	common symbols. Report old filename when symbol size changes.

  Approved and applied.

Cheers
        Nick


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH: Fix alignment of common symbol
  2003-04-14 11:07   ` Nick Clifton
@ 2003-04-14 19:33     ` H. J. Lu
  2003-04-15  9:38       ` Nick Clifton
  0 siblings, 1 reply; 5+ messages in thread
From: H. J. Lu @ 2003-04-14 19:33 UTC (permalink / raw)
  To: Nick Clifton; +Cc: binutils

[-- Attachment #1: Type: text/plain, Size: 264 bytes --]

On Mon, Apr 14, 2003 at 12:06:56PM +0100, Nick Clifton wrote:
> Hi H.J.
> 
>   Thanks for catching this.  Do you think that it is worth developing
>   a linker test case to check for this ?

That is a good idea. Here it is. It caught a bug in my patch :-).


H.J.

[-- Attachment #2: binutils-common-test.patch --]
[-- Type: text/plain, Size: 5528 bytes --]

bfd/

2003-04-14  H.J. Lu <hjl@gnu.org>

	* elflink.h (elf_link_add_object_symbols): Properly report
	filename for alignment reduction.

ld/testsuite/

	* ld-elfcom/elfcom.exp: New file.
	* ld-elfcom/common1a.c: New file.
	* ld-elfcom/common1b.c: New file.

2003-04-14  H.J. Lu <hjl@gnu.org>


--- binutils/bfd/elflink.h.common-test	2003-04-14 08:17:52.000000000 -0700
+++ binutils/bfd/elflink.h	2003-04-14 12:22:05.000000000 -0700
@@ -2036,6 +2036,7 @@ elf_link_add_object_symbols (abfd, info)
 	      && h->root.type != bfd_link_hash_common)
 	    {
 	      unsigned int common_align, normal_align, symbol_align;
+	      bfd *normal_bfd, *common_bfd;
 
 	      symbol_align = ffs (h->root.u.def.value) - 1;
 	      if ((h->root.u.def.section->owner->flags & DYNAMIC) == 0)
@@ -2048,16 +2049,25 @@ elf_link_add_object_symbols (abfd, info)
 		normal_align = symbol_align;
 
 	      if (old_alignment)
-		common_align = old_alignment;
+		{
+		  common_align = old_alignment;
+		  common_bfd = old_bfd;
+		  normal_bfd = abfd;
+		}
 	      else
-		common_align = bfd_log2 (isym->st_value);
+		{
+		  common_align = bfd_log2 (isym->st_value);
+		  common_bfd = abfd;
+		  normal_bfd = old_bfd;
+		}
 
 	      if (normal_align < common_align)
 		(*_bfd_error_handler)
 		  (_("Warning: alignment %u of symbol `%s' in %s is smaller than %u in %s"),
 		   1 << normal_align, name,
-		   bfd_archive_filename (old_bfd),
-		   1 << common_align, bfd_archive_filename (abfd));
+		   bfd_archive_filename (normal_bfd),
+		   1 << common_align,
+		   bfd_archive_filename (common_bfd));
 	    }
 
 	  /* Remember the symbol size and type.  */
--- binutils/ld/testsuite/ld-elfcom/common1a.c.common-test	2003-04-14 12:28:20.000000000 -0700
+++ binutils/ld/testsuite/ld-elfcom/common1a.c	2003-04-14 11:24:27.000000000 -0700
@@ -0,0 +1,2 @@
+char foo1 [2] __attribute__((aligned(64)));
+char foo2 [2] __attribute__((aligned(128)));
--- binutils/ld/testsuite/ld-elfcom/common1b.c.common-test	2003-04-14 12:28:20.000000000 -0700
+++ binutils/ld/testsuite/ld-elfcom/common1b.c	2003-04-14 11:24:33.000000000 -0700
@@ -0,0 +1,3 @@
+static char dummy1 = 'X';
+char foo1 [] = "Aligned at odd byte.";
+char foo2 [4];
--- binutils/ld/testsuite/ld-elfcom/elfcom.exp.common-test	2003-04-14 12:28:20.000000000 -0700
+++ binutils/ld/testsuite/ld-elfcom/elfcom.exp	2003-04-14 12:27:37.000000000 -0700
@@ -0,0 +1,92 @@
+# Expect script for commom symbol tests
+#   Copyright 2003 Free Software Foundation, Inc.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Written by H.J. Lu (hjl@gnu.org)
+#
+
+# Make sure that ld correctly handles common symbols in ELF.
+
+# This test can only be run on ELF platforms.
+# Square bracket expressions seem to confuse istarget.
+if { ![istarget hppa*64*-*-hpux*] \
+     && ![istarget *-*-gnu] \
+     && ![istarget *-*-linux*] \
+     && ![istarget *-*-elf] } {
+    return
+}
+
+if { [istarget *-*-linux*aout*] \
+     || [istarget *-*-linux*oldld*] } {
+    return
+}
+
+proc dump_common1 { testname } {
+    global exec_output
+
+    send_log "readelf -s tmpdir/common1.o | grep foo\n"
+    catch "exec readelf -s tmpdir/common1.o | grep foo" exec_output
+    if { ![regexp "(\[ 	\]*)(\[0-9\]+):(\[ 	\]*)(\[0\]*)80(\[ 	\]+)4(\[ 	\]+)OBJECT(\[ 	\]+)GLOBAL(\[ 	\]+)DEFAULT(\[ 	\]+)COM(\[ 	\]+)foo2" $exec_output]
+ 	 || ![regexp "(\[ 	\]*)(\[0-9\]+):(\[ 	\]*)(\[0\]*)1(\[ 	\]+)21(\[ 	\]+)OBJECT(\[ 	\]+)GLOBAL(\[ 	\]+)DEFAULT(\[ 	\]+)(\[0-9\]+)(\[ 	\]+)foo1" $exec_output] } {
+	send_log "$exec_output\n"
+	verbose $exec_output
+	fail $testname
+	return 0
+    }
+
+    return 1
+}
+
+set test1 "size/aligment change of commom symbols"
+if { ![ld_compile "$CC $CFLAGS" $srcdir/$subdir/common1a.c tmpdir/common1a.o]
+    || ![ld_compile "$CC $CFLAGS" $srcdir/$subdir/common1b.c tmpdir/common1b.o] } {
+    unresolved $test1
+    return
+}
+
+global ld
+global link_output
+
+if { [ld_simple_link $ld tmpdir/common1.o "-r tmpdir/common1a.o tmpdir/common1b.o"] } {
+    unresolved $test1
+    return
+}
+
+if { ![regexp "Warning: alignment 1 of symbol \`foo1\' in tmpdir/common1b.o is smaller than 64 in tmpdir/common1a.o" $link_output]
+     || ![regexp "Warning: size of symbol \`foo1\' changed from 2 in tmpdir/common1a.o to 21 in tmpdir/common1b.o" $link_output] } {
+    fail "$test1 (warning 1)"
+} else {
+    pass "$test1 (warning 1)"
+}
+
+if { [dump_common1 "$test1 (change 1)"] } {
+    pass "$test1 (change 1)"
+}
+
+if { [ld_simple_link $ld tmpdir/common1.o "-r tmpdir/common1b.o tmpdir/common1a.o"] } {
+    unresolved $test1
+    return
+}
+
+if { ![regexp "Warning: alignment 1 of symbol \`foo1\' in tmpdir/common1b.o is smaller than 64 in tmpdir/common1a.o" $link_output] } {
+    fail "$test1 (warning 2)"
+} else {
+    pass "$test1 (warningi 2)"
+}
+
+if { [dump_common1 "$test1 (change 2)"] } {
+    pass "$test1 (change 2)"
+}

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH: Fix alignment of common symbol
  2003-04-14 19:33     ` H. J. Lu
@ 2003-04-15  9:38       ` Nick Clifton
  0 siblings, 0 replies; 5+ messages in thread
From: Nick Clifton @ 2003-04-15  9:38 UTC (permalink / raw)
  To: H. J. Lu; +Cc: binutils

Hi H.J.

> bfd/
> 
> 2003-04-14  H.J. Lu <hjl@gnu.org>
> 
> 	* elflink.h (elf_link_add_object_symbols): Properly report
> 	filename for alignment reduction.
> 
> ld/testsuite/
> 
> 	* ld-elfcom/elfcom.exp: New file.
> 	* ld-elfcom/common1a.c: New file.
> 	* ld-elfcom/common1b.c: New file.

Thanks!  Approved and applied.

Cheers
        Nick

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2003-04-15  9:38 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-04-10 18:26 PATCH: Fix alignment of common symbol H. J. Lu
2003-04-11 16:08 ` H. J. Lu
2003-04-14 11:07   ` Nick Clifton
2003-04-14 19:33     ` H. J. Lu
2003-04-15  9:38       ` Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).