* 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.
This commit is contained in:
Richard Sandiford 2011-03-14 15:52:53 +00:00
parent 47beaa6a21
commit b436d85411
10 changed files with 130 additions and 83 deletions

View 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.

View 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;
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 (sym_flags == STT_ARM_TFUNC)
value |= 1;
bfd_put_32 (output_bfd, value, sgot->contents + off);
h->got.offset |= 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
*unresolved_reloc_p = FALSE;
{
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 (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)
outrel.r_addend |= 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;
}
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;

View 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.

View 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"

View File

@ -0,0 +1,4 @@
Relocation section '\.rel\.dyn' .*
Offset .*
.* R_ARM_GLOB_DAT * 00000000 * foo

View File

@ -0,0 +1,5 @@
.globl foo
.type foo,%object
.size foo,4
.data
foo: .word 1

View File

@ -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

View File

@ -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

View File

@ -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 .*

View File

@ -0,0 +1,6 @@
.globl _start
_start:
ldr r4,1f
mov pc,lr
1:
.word foo(GOT)