aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2011-03-14 15:52:53 +0000
committerRichard Sandiford <rdsandiford@googlemail.com>2011-03-14 15:52:53 +0000
commitb436d85411e682b845d3d0d1d385e00504a4411a (patch)
tree96d6b4dca871a4eb7e8b2c13cdad2f7b54091485
parent47beaa6a213f48eaf6e0bd3d3768ba559c42b1b6 (diff)
downloadfsf-binutils-gdb-b436d85411e682b845d3d0d1d385e00504a4411a.zip
fsf-binutils-gdb-b436d85411e682b845d3d0d1d385e00504a4411a.tar.gz
fsf-binutils-gdb-b436d85411e682b845d3d0d1d385e00504a4411a.tar.bz2
bfd/
* 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.
-rw-r--r--bfd/ChangeLog10
-rw-r--r--bfd/elf32-arm.c139
-rw-r--r--ld/testsuite/ChangeLog7
-rw-r--r--ld/testsuite/ld-arm/arm-elf.exp10
-rw-r--r--ld/testsuite/ld-arm/exec-got-1.d4
-rw-r--r--ld/testsuite/ld-arm/exec-got-1a.s5
-rw-r--r--ld/testsuite/ld-arm/exec-got-1b.s10
-rw-r--r--ld/testsuite/ld-arm/unresolved-1-dyn.d8
-rw-r--r--ld/testsuite/ld-arm/unresolved-1.d8
-rw-r--r--ld/testsuite/ld-arm/unresolved-1.s6
10 files changed, 127 insertions, 80 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 4412a17..bb59da1 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,5 +1,15 @@
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.
(elf32_arm_add_dynreloc): Likewise.
(elf32_arm_adjust_dynamic_symbol): Use elf32_arm_allocate_dynrelocs
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 1a96731..1383090 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -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;
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index 603089c..fdeaf77 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -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.
diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp
index 798b2cb..dcdc231 100644
--- a/ld/testsuite/ld-arm/arm-elf.exp
+++ b/ld/testsuite/ld-arm/arm-elf.exp
@@ -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
index 0000000..af067d3
--- /dev/null
+++ b/ld/testsuite/ld-arm/exec-got-1.d
@@ -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
index 0000000..6a7637c
--- /dev/null
+++ b/ld/testsuite/ld-arm/exec-got-1a.s
@@ -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
index 0000000..71546d7
--- /dev/null
+++ b/ld/testsuite/ld-arm/exec-got-1b.s
@@ -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
index 0000000..21cd959
--- /dev/null
+++ b/ld/testsuite/ld-arm/unresolved-1-dyn.d
@@ -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
index 0000000..cfc1b04
--- /dev/null
+++ b/ld/testsuite/ld-arm/unresolved-1.d
@@ -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
index 0000000..4db4aea
--- /dev/null
+++ b/ld/testsuite/ld-arm/unresolved-1.s
@@ -0,0 +1,6 @@
+ .globl _start
+_start:
+ ldr r4,1f
+ mov pc,lr
+1:
+ .word foo(GOT)