===================================================================
@@ -8278,45 +8278,67 @@ elf32_arm_final_link_relocate (reloc_how
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 ((off & 1) != 0)
+ {
+ /* 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 (! 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))
- {
- /* 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;
+ 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 (struct elf_link_hash
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 * o
}
}
- 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;
===================================================================
@@ -0,0 +1,5 @@
+ .globl foo
+ .type foo,%object
+ .size foo,4
+ .data
+foo: .word 1
===================================================================
@@ -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
===================================================================
@@ -0,0 +1,4 @@
+
+Relocation section '\.rel\.dyn' .*
+ Offset .*
+.* R_ARM_GLOB_DAT * 00000000 * foo
===================================================================
@@ -0,0 +1,6 @@
+ .globl _start
+_start:
+ ldr r4,1f
+ mov pc,lr
+1:
+ .word foo(GOT)
===================================================================
@@ -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 .*
===================================================================
@@ -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
===================================================================
@@ -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"