PATCH: PR ld/13250: unresolvable R_X86_64_64 relocations with ld --as-needed

H.J. Lu hongjiu.lu@intel.com
Fri Oct 7 19:12:00 GMT 2011


With --as-needed, we find libfoo.so isn't needed to resolve any references
in the relocatable inputs.  So we don't add it to DT_NEEDED and restore
the symbol table.   But libfoo.so is on the DT_NEEDED list in an input
shared library, libbar.so, and we load libfoo.so to again to resolve
references in libbar.so.  Since libfoo.so has been loaded by linker the
first one, we don't set its output section the second time.

However, libfoo.so does change alignment and size for common symbols
in the relocatable inputs and updates its section:

         if (section == bfd_com_section_ptr)
            {    
              h->u.c.p->section = bfd_make_section_old_way (abfd,
"COMMON");
              h->u.c.p->section->flags |= SEC_ALLOC;
            }    
          else if (section->owner != abfd)
            {    
              h->u.c.p->section = bfd_make_section_old_way (abfd,
                                                            section->name);
              h->u.c.p->section->flags |= SEC_ALLOC;
            }    
          else 
            h->u.c.p->section = section;

Now, we have a common symbol defined in a section without
output section.

As the testcase show, libfoo.so is used at the run-time.
We should preserve the maximum alignment and size.  OK to
install?

Thanks.


H.J.
---
bfd/

2011-10-07  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/13250
	* elflink.c (elf_link_add_object_symbols): Preserve the maximum
	alignment and size for common symbols.

ld/testsuite/

2011-10-07  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/13250
	* ld-elf/shared.exp (build_tests): Add tests for PR ld/13250.
	(run_tests): Likewise.

	* ld-elf/pr13250-1.c: New.
	* ld-elf/pr13250-2.c: Likewise.
	* ld-elf/pr13250-3.c: Likewise.

diff --git a/bfd/elflink.c b/bfd/elflink.c
index 5d181f7..3134df9 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -4513,6 +4513,8 @@ error_free_dyn:
 	{
 	  struct bfd_hash_entry *p;
 	  struct elf_link_hash_entry *h;
+	  bfd_size_type size;
+	  unsigned int alignment_power;
 
 	  for (p = htab->root.table.table[i]; p != NULL; p = p->next)
 	    {
@@ -4522,6 +4524,20 @@ error_free_dyn:
 	      if (h->dynindx >= old_dynsymcount)
 		_bfd_elf_strtab_delref (htab->dynstr, h->dynstr_index);
 
+	      /* Preserve the maximum alignment and size for common
+		 symbols even if this dynamic lib isn't on DT_NEEDED
+		 since it can still be loaded at the run-time by another
+		 dynamic lib.  */
+	      if (h->root.type == bfd_link_hash_common)
+		{
+		  size = h->root.u.c.size;
+		  alignment_power = h->root.u.c.p->alignment_power;
+		}
+	      else
+		{
+		  size = 0;
+		  alignment_power = 0;
+		}
 	      memcpy (p, old_ent, htab->root.table.entsize);
 	      old_ent = (char *) old_ent + htab->root.table.entsize;
 	      h = (struct elf_link_hash_entry *) p;
@@ -4530,6 +4546,13 @@ error_free_dyn:
 		  memcpy (h->root.u.i.link, old_ent, htab->root.table.entsize);
 		  old_ent = (char *) old_ent + htab->root.table.entsize;
 		}
+	      else if (h->root.type == bfd_link_hash_common)
+		{
+		  if (size > h->root.u.c.size)
+		    h->root.u.c.size = size;
+		  if (alignment_power > h->root.u.c.p->alignment_power)
+		    h->root.u.c.p->alignment_power = alignment_power;
+		}
 	    }
 	}
 
diff --git a/ld/testsuite/ld-elf/pr13250-1.c b/ld/testsuite/ld-elf/pr13250-1.c
new file mode 100644
index 0000000..e43ebe0
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr13250-1.c
@@ -0,0 +1,8 @@
+int common1[8];
+void
+foo ()
+{
+  int i;
+  for (i = 0; i < sizeof (common1)/ sizeof (common1[0]); i++)
+    common1[i] = -1;
+}
diff --git a/ld/testsuite/ld-elf/pr13250-2.c b/ld/testsuite/ld-elf/pr13250-2.c
new file mode 100644
index 0000000..af8268b
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr13250-2.c
@@ -0,0 +1,10 @@
+extern int common1[8];
+
+extern void foo ();
+
+int
+bar ()
+{
+  foo ();
+  return common1[4];
+}
diff --git a/ld/testsuite/ld-elf/pr13250-3.c b/ld/testsuite/ld-elf/pr13250-3.c
new file mode 100644
index 0000000..a227670
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr13250-3.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+int common1[1];
+char common2[2];
+
+extern int bar ();
+
+int
+main ()
+{
+  int i;
+  if (bar () != -1)
+    abort ();
+  if (common1[0] != -1)
+    abort ();
+  for (i = 0; i < sizeof (common2)/ sizeof (common2[0]); i++)
+    if (common2[i] != 0)
+      abort ();
+  printf ("PASS\n");
+  return 0;
+}
diff --git a/ld/testsuite/ld-elf/shared.exp b/ld/testsuite/ld-elf/shared.exp
index eea9c7e..9cd0221 100644
--- a/ld/testsuite/ld-elf/shared.exp
+++ b/ld/testsuite/ld-elf/shared.exp
@@ -157,6 +157,15 @@ set build_tests {
   {"Build libpr11138-2.o"
    "-r -nostdlib" ""
    {pr11138-2.c} {} "libpr11138-2.o"}
+  {"Build pr13250-1.so"
+   "-shared" "-fPIC"
+   {pr13250-1.c} {} "libpr13250-1.so"}
+  {"Build pr13250-2.so with libpr13250-1.so"
+   "-shared tmpdir/libpr13250-1.so" "-fPIC"
+   {pr13250-2.c} {} "libpr13250-2.so"}
+  {"Build libpr13250-3.o"
+   "-r -nostdlib" ""
+   {pr13250-3.c} {} "libpr13250-3.o"}
 }
 
 run_cc_link_tests $build_tests
@@ -283,6 +292,9 @@ set run_tests {
     {"Run with libpr11138-1.so pr11138-2.c"
      "--version-script=pr11138-2.map tmpdir/libpr11138-1.so tmpdir/pr11138-2.o" ""
      {dummy.c} "pr11138b" "pr11138.out"}
+    {"Run with pr13250-3.c, libpr13250-1.so and libpr13250-2.so"
+     "--as-needed tmpdir/pr13250-3.o tmpdir/libpr13250-1.so tmpdir/libpr13250-2.so" ""
+     {dummy.c} "pr13250" "pass.out"}
 }
 
 # NetBSD ELF systems do not currently support the .*_array sections.



More information about the Binutils mailing list