From: Richard Sandiford <richard.sandiford@linaro.org>
To: binutils@sourceware.org
Cc: patches@linaro.org
Subject: [2/6] Always initialise ARM got entries in final_link_relocate
Date: Fri, 04 Mar 2011 16:06:00 -0000 [thread overview]
Message-ID: <g4bp1qvpjx.fsf@linaro.org> (raw)
Current linkers generate dynamic GOT relocations for global-but-locally-
binding symbols in executables. E.g.:
.globl foo
.type fo,%function
foo:
ldr r1,1f
1:
.word foo(GOT)
.size foo,.-foo
generates a dynamic R_ARM_GLOB_DAT entry for foo (even though, of course,
all other references to foo, such as through absolute accesses or calls,
would not have dynamic reloctions). This behaviour isn't specific to ARM,
but it seems like unnecessary bloat.
The reason I looked at this is that we currently have a rather awkward
split in the way we initialise GOT entries. We initialise GOT entries for
dynamic symbols in elf32_arm_finish_dynamic_symbol, but we initalise all
other GOT entries in elf32_arm_final_link_relocate. We then have to be
careful which case we're dealing with:
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. */
This gets even more complicated with ifuncs, where we may need irelative
relocations. It seemed easier to handle everything in one place, and to
fix the unnecessary relocs described above while there.
The patch also includes a testcase (unresolved-1) to show why the
dynamic_sections_created condition is important. We already pass
the test, but I thought it was worth including to make sure that
we don't regress in future.
Tested on arm-linux-gnueabi. OK to install?
Richard
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.
Index: bfd/elf32-arm.c
===================================================================
--- bfd/elf32-arm.c 2011-03-04 10:41:18.000000000 +0000
+++ bfd/elf32-arm.c 2011-03-04 15:57:59.000000000 +0000
@@ -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;
Index: ld/testsuite/ld-arm/exec-got-1a.s
===================================================================
--- /dev/null 2011-02-21 12:47:04.267827113 +0000
+++ ld/testsuite/ld-arm/exec-got-1a.s 2011-03-04 12:57:49.000000000 +0000
@@ -0,0 +1,5 @@
+ .globl foo
+ .type foo,%object
+ .size foo,4
+ .data
+foo: .word 1
Index: ld/testsuite/ld-arm/exec-got-1b.s
===================================================================
--- /dev/null 2011-02-21 12:47:04.267827113 +0000
+++ ld/testsuite/ld-arm/exec-got-1b.s 2011-03-04 12:57:49.000000000 +0000
@@ -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
Index: ld/testsuite/ld-arm/exec-got-1.d
===================================================================
--- /dev/null 2011-02-21 12:47:04.267827113 +0000
+++ ld/testsuite/ld-arm/exec-got-1.d 2011-03-04 12:57:49.000000000 +0000
@@ -0,0 +1,4 @@
+
+Relocation section '\.rel\.dyn' .*
+ Offset .*
+.* R_ARM_GLOB_DAT * 00000000 * foo
Index: ld/testsuite/ld-arm/unresolved-1.s
===================================================================
--- /dev/null 2011-02-21 12:47:04.267827113 +0000
+++ ld/testsuite/ld-arm/unresolved-1.s 2011-03-04 12:57:49.000000000 +0000
@@ -0,0 +1,6 @@
+ .globl _start
+_start:
+ ldr r4,1f
+ mov pc,lr
+1:
+ .word foo(GOT)
Index: ld/testsuite/ld-arm/unresolved-1.d
===================================================================
--- /dev/null 2011-02-21 12:47:04.267827113 +0000
+++ ld/testsuite/ld-arm/unresolved-1.d 2011-03-04 12:57:49.000000000 +0000
@@ -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 .*
Index: ld/testsuite/ld-arm/unresolved-1-dyn.d
===================================================================
--- /dev/null 2011-02-21 12:47:04.267827113 +0000
+++ ld/testsuite/ld-arm/unresolved-1-dyn.d 2011-03-04 12:57:49.000000000 +0000
@@ -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
Index: ld/testsuite/ld-arm/arm-elf.exp
===================================================================
--- ld/testsuite/ld-arm/arm-elf.exp 2011-03-04 10:40:28.000000000 +0000
+++ ld/testsuite/ld-arm/arm-elf.exp 2011-03-04 15:57:05.000000000 +0000
@@ -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"
next reply other threads:[~2011-03-04 16:06 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-03-04 16:06 Richard Sandiford [this message]
2011-03-14 14:12 ` Nick Clifton
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=g4bp1qvpjx.fsf@linaro.org \
--to=richard.sandiford@linaro.org \
--cc=binutils@sourceware.org \
--cc=patches@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).