bfd/
authorRichard Sandiford <rdsandiford@googlemail.com>
Mon, 14 Mar 2011 15:52:53 +0000 (15:52 +0000)
committerRichard Sandiford <rdsandiford@googlemail.com>
Mon, 14 Mar 2011 15:52:53 +0000 (15:52 +0000)
* elf32-arm.c (elf32_arm_final_link_relocate): Always fill in the
GOT entry here, rather than leaving it to finish_dynamic_symbol.
Only create a dynamic relocation for local references if
info->shared.
(allocate_dynrelocs_for_symbol): Update dynamic relocation
allocation accordingly.
(elf32_arm_finish_dynamic_symbol): Don't initialise the GOT entry here.

ld/testsuite/
* ld-arm/exec-got-1a.s, ld-arm/exec-got-1b.s, ld-arm/exec-got-1.d,
ld-arm/unresolved-1.s, ld-arm/unresolved-1.d,
ld-arm/unresolved-1-dyn.d: New tests.
* ld-arm/arm-elf.exp: Run them.

bfd/ChangeLog
bfd/elf32-arm.c
ld/testsuite/ChangeLog
ld/testsuite/ld-arm/arm-elf.exp
ld/testsuite/ld-arm/exec-got-1.d [new file with mode: 0644]
ld/testsuite/ld-arm/exec-got-1a.s [new file with mode: 0644]
ld/testsuite/ld-arm/exec-got-1b.s [new file with mode: 0644]
ld/testsuite/ld-arm/unresolved-1-dyn.d [new file with mode: 0644]
ld/testsuite/ld-arm/unresolved-1.d [new file with mode: 0644]
ld/testsuite/ld-arm/unresolved-1.s [new file with mode: 0644]

index 4412a1764198e6c958c40ad997d26f46bd9eb8f7..bb59da145252b5f4fa85ae27db97ec42bab3a2fa 100644 (file)
@@ -1,3 +1,13 @@
+2011-03-14  Richard Sandiford  <richard.sandiford@linaro.org>
+
+       * elf32-arm.c (elf32_arm_final_link_relocate): Always fill in the
+       GOT entry here, rather than leaving it to finish_dynamic_symbol.
+       Only create a dynamic relocation for local references if
+       info->shared.
+       (allocate_dynrelocs_for_symbol): Update dynamic relocation
+       allocation accordingly.
+       (elf32_arm_finish_dynamic_symbol): Don't initialise the GOT entry here.
+
 2011-03-14  Richard Sandiford  <richard.sandiford@linaro.org>
 
        * elf32-arm.c (elf32_arm_allocate_dynrelocs): New function.
index 1a967312a8ff69c26fb909da4a6f6d212a6d747a..138309018750d07c5d58ed60daa6d2775f22d59d 100644 (file)
@@ -8278,45 +8278,67 @@ elf32_arm_final_link_relocate (reloc_howto_type *           howto,
       if (h != NULL)
        {
          bfd_vma off;
-         bfd_boolean dyn;
 
          off = h->got.offset;
          BFD_ASSERT (off != (bfd_vma) -1);
-         dyn = globals->root.dynamic_sections_created;
-
-         if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
-             || (info->shared
-                 && SYMBOL_REFERENCES_LOCAL (info, h))
-             || (ELF_ST_VISIBILITY (h->other)
-                 && h->root.type == bfd_link_hash_undefweak))
+         if ((off & 1) != 0)
            {
-             /* This is actually a static link, or it is a -Bsymbolic link
-                and the symbol is defined locally.  We must initialize this
-                entry in the global offset table.  Since the offset must
-                always be a multiple of 4, we use the least significant bit
-                to record whether we have initialized it already.
-
-                When doing a dynamic link, we create a .rel(a).got relocation
-                entry to initialize the value.  This is done in the
-                finish_dynamic_symbol routine.  */
-             if ((off & 1) != 0)
-               off &= ~1;
+             /* We have already processsed one GOT relocation against
+                this symbol.  */
+             off &= ~1;
+             if (globals->root.dynamic_sections_created
+                 && !SYMBOL_REFERENCES_LOCAL (info, h))
+               *unresolved_reloc_p = FALSE;
+           }
+         else
+           {
+             Elf_Internal_Rela outrel;
+
+             if (!SYMBOL_REFERENCES_LOCAL (info, h))
+               {
+                 /* If the symbol doesn't resolve locally in a static
+                    object, we have an undefined reference.  If the
+                    symbol doesn't resolve locally in a dynamic object,
+                    it should be resolved by the dynamic linker.  */
+                 if (globals->root.dynamic_sections_created)
+                   {
+                     outrel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_GLOB_DAT);
+                     *unresolved_reloc_p = FALSE;
+                   }
+                 else
+                   outrel.r_info = 0;
+                 outrel.r_addend = 0;
+               }
              else
                {
-                 /* If we are addressing a Thumb function, we need to
-                    adjust the address by one, so that attempts to
-                    call the function pointer will correctly
-                    interpret it as Thumb code.  */
+                 if (info->shared)
+                   outrel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE);
+                 else
+                   outrel.r_info = 0;
+                 outrel.r_addend = value;
                  if (sym_flags == STT_ARM_TFUNC)
-                   value |= 1;
+                   outrel.r_addend |= 1;
+               }
 
-                 bfd_put_32 (output_bfd, value, sgot->contents + off);
-                 h->got.offset |= 1;
+             /* The GOT entry is initialized to zero by default.
+                See if we should install a different value.  */
+             if (outrel.r_addend != 0
+                 && (outrel.r_info == 0 || globals->use_rel))
+               {
+                 bfd_put_32 (output_bfd, outrel.r_addend,
+                             sgot->contents + off);
+                 outrel.r_addend = 0;
                }
-           }
-         else
-           *unresolved_reloc_p = FALSE;
 
+             if (outrel.r_info != 0)
+               {
+                 outrel.r_offset = (sgot->output_section->vma
+                                    + sgot->output_offset
+                                    + off);
+                 elf32_arm_add_dynreloc (output_bfd, info, srelgot, &outrel);
+               }
+             h->got.offset |= 1;
+           }
          value = sgot->output_offset + off;
        }
       else
@@ -12222,10 +12244,14 @@ allocate_dynrelocs_for_symbol (struct elf_link_hash_entry *h, void * inf)
              if ((tls_type & GOT_TLS_GD) && indx != 0)  
                elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1);
            }
-         else if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-                   || h->root.type != bfd_link_hash_undefweak)
-                  && (info->shared
-                  || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)))
+         else if (!SYMBOL_REFERENCES_LOCAL (info, h))
+           {
+             if (htab->root.dynamic_sections_created)
+               /* Reserve room for the GOT entry's R_ARM_GLOB_DAT relocation.  */
+               elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1);
+           }
+         else if (info->shared)
+           /* Reserve room for the GOT entry's R_ARM_RELATIVE relocation.  */
            elf32_arm_allocate_dynrelocs (info, htab->root.srelgot, 1);
        }
     }
@@ -13016,53 +13042,6 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd,
        }
     }
 
-  if (h->got.offset != (bfd_vma) -1
-      && (! GOT_TLS_GD_ANY_P (elf32_arm_hash_entry (h)->tls_type)) 
-      && (elf32_arm_hash_entry (h)->tls_type & GOT_TLS_IE) == 0)
-    {
-      asection * sgot;
-      asection * srel;
-      Elf_Internal_Rela rel;
-      bfd_vma offset;
-
-      /* This symbol has an entry in the global offset table.  Set it
-        up.  */
-      sgot = htab->root.sgot;
-      srel = htab->root.srelgot;
-      BFD_ASSERT (sgot != NULL && srel != NULL);
-
-      offset = (h->got.offset & ~(bfd_vma) 1);
-      rel.r_addend = 0;
-      rel.r_offset = (sgot->output_section->vma
-                     + sgot->output_offset
-                     + offset);
-
-      /* If this is a static link, or it is a -Bsymbolic link and the
-        symbol is defined locally or was forced to be local because
-        of a version file, we just want to emit a RELATIVE reloc.
-        The entry in the global offset table will already have been
-        initialized in the relocate_section function.  */
-      if (info->shared
-         && SYMBOL_REFERENCES_LOCAL (info, h))
-       {
-         BFD_ASSERT ((h->got.offset & 1) != 0);
-         rel.r_info = ELF32_R_INFO (0, R_ARM_RELATIVE);
-         if (!htab->use_rel)
-           {
-             rel.r_addend = bfd_get_32 (output_bfd, sgot->contents + offset);
-             bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + offset);
-           }
-       }
-      else
-       {
-         BFD_ASSERT ((h->got.offset & 1) == 0);
-         bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents + offset);
-         rel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_GLOB_DAT);
-       }
-
-      elf32_arm_add_dynreloc (output_bfd, info, srel, &rel);
-    }
-
   if (h->needs_copy)
     {
       asection * s;
index 603089cedddf65b2aa2282e6bb60a8ad32bd5ed4..fdeaf77c1b99cfc720cd2c5f2ed0dca85a4240e8 100644 (file)
@@ -1,3 +1,10 @@
+2011-03-14  Richard Sandiford  <richard.sandiford@linaro.org>
+
+       * ld-arm/exec-got-1a.s, ld-arm/exec-got-1b.s, ld-arm/exec-got-1.d,
+       ld-arm/unresolved-1.s, ld-arm/unresolved-1.d,
+       ld-arm/unresolved-1-dyn.d: New tests.
+       * ld-arm/arm-elf.exp: Run them.
+
 2011-03-12  H.J. Lu  <hongjiu.lu@intel.com>
 
        * ld-x86-64/tlsgd4.dd: New.
index 798b2cb5af35316164238ef020c1576eed942b03..dcdc2310d44f993d3267b9087ee2f59a9f6cbac1 100644 (file)
@@ -295,6 +295,14 @@ set armelftests {
     {"Data only mapping symbols" "-T data-only-map.ld -Map map" "" {data-only-map.s}
      {{objdump -dr data-only-map.d}}
      "data-only-map"}
+    {"GOT relocations in executables (setup)" "-shared"
+     "" {exec-got-1a.s}
+     {}
+     "exec-got-1.so"}
+    {"GOT relocations in executables" "tmpdir/exec-got-1.so"
+     "" {exec-got-1b.s}
+     {{readelf --relocs exec-got-1.d}}
+     "exec-got-1"}
 }
 
 run_ld_link_tests $armelftests
@@ -582,3 +590,5 @@ run_dump_test "attr-merge-vfp-5r"
 run_dump_test "attr-merge-vfp-6"
 run_dump_test "attr-merge-vfp-6r"
 run_dump_test "attr-merge-incompatible"
+run_dump_test "unresolved-1"
+run_dump_test "unresolved-1-dyn"
diff --git a/ld/testsuite/ld-arm/exec-got-1.d b/ld/testsuite/ld-arm/exec-got-1.d
new file mode 100644 (file)
index 0000000..af067d3
--- /dev/null
@@ -0,0 +1,4 @@
+
+Relocation section '\.rel\.dyn' .*
+ Offset .*
+.* R_ARM_GLOB_DAT * 00000000 * foo
diff --git a/ld/testsuite/ld-arm/exec-got-1a.s b/ld/testsuite/ld-arm/exec-got-1a.s
new file mode 100644 (file)
index 0000000..6a7637c
--- /dev/null
@@ -0,0 +1,5 @@
+       .globl  foo
+       .type   foo,%object
+       .size   foo,4
+       .data
+foo:   .word   1
diff --git a/ld/testsuite/ld-arm/exec-got-1b.s b/ld/testsuite/ld-arm/exec-got-1b.s
new file mode 100644 (file)
index 0000000..71546d7
--- /dev/null
@@ -0,0 +1,10 @@
+       .globl  _start
+       .type   _start,%function
+_start:
+       ldr     r1,1f
+       ldr     r1,2f
+1:
+       .word   foo(GOT)
+2:
+       .word   _start(GOT)
+       .size   _start,.-_start
diff --git a/ld/testsuite/ld-arm/unresolved-1-dyn.d b/ld/testsuite/ld-arm/unresolved-1-dyn.d
new file mode 100644 (file)
index 0000000..21cd959
--- /dev/null
@@ -0,0 +1,8 @@
+#source: unresolved-1.s
+#ld: --warn-unresolved tmpdir/mixed-lib.so
+#warning: \(\.text\+0x8\): warning: undefined reference to `foo'
+#readelf: -r
+
+Relocation section '\.rel\.dyn' .*
+ Offset .*
+.* R_ARM_GLOB_DAT +00000000 +foo
diff --git a/ld/testsuite/ld-arm/unresolved-1.d b/ld/testsuite/ld-arm/unresolved-1.d
new file mode 100644 (file)
index 0000000..cfc1b04
--- /dev/null
@@ -0,0 +1,8 @@
+#ld: --warn-unresolved
+#warning: \(\.text\+0x8\): warning: undefined reference to `foo'
+#objdump: -sj.rel.dyn -sj.got
+
+.*
+
+Contents of section \.got:
+ *[^ ]* 00000000 00000000 00000000 00000000  .*
diff --git a/ld/testsuite/ld-arm/unresolved-1.s b/ld/testsuite/ld-arm/unresolved-1.s
new file mode 100644 (file)
index 0000000..4db4aea
--- /dev/null
@@ -0,0 +1,6 @@
+       .globl  _start
+_start:
+       ldr     r4,1f
+       mov     pc,lr
+1:
+       .word   foo(GOT)