PATCH: Fix alignment of common symbol

H. J. Lu hjl@lucon.org
Thu Apr 10 18:26:00 GMT 2003


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.
-------------- next part --------------
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))
-------------- next part --------------
A non-text attachment was scrubbed...
Name: bug.tar.gz
Type: application/x-gzip
Size: 662 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/binutils/attachments/20030410/20bd1204/attachment.bin>


More information about the Binutils mailing list