[AArch64] Allow COPY relocation elimination

As discussed at the PR, this patch tries to avoid COPY relocation generation
and propagate the original relocation into runtime if it was relocating on
writable section.  The ELIMINATE_COPY_RELOCS has been set to true and it's
underlying infrastructure has been improved so that the COPY reloc elimination
at least working on absoluate relocations (ABS64) on AArch64.

  BFD linker copy relocation elimination framwork requires the backend to always
allocate dynrelocs for all those relocation types that are possible to introduce
copy relocations.  This is for adjust_dynamic_symbol hook to be able to get all
symbol reference information.  Should one symbol is referenced by more than one
relocations, if there is any of them needs copy relocation then linker should
generate it.

bfd/
	PR ld/21532
	* elfnn-aarch64.c (ELIMINATE_COPY_RELOCS): Set to 1.
	(elfNN_aarch64_final_link_relocate): Also propagate relocations to
	runtime for if there needs copy relocation elimination.
	(need_copy_relocation_p): New function.  Return true for symbol with
	pc-relative references and if it's against read-only sections.
	(elfNN_aarch64_adjust_dynamic_symbol): Use need_copy_relocation_p.
	(elfNN_aarch64_check_relocs): Allocate dynrelocs for relocation types
	that are related with accessing external objects.
	(elfNN_aarch64_gc_sweep_hook): Sync the relocation types with the change
	in elfNN_aarch64_check_relocs.

ld/
	* testsuite/ld-aarch64/copy-reloc-exe-2.s: New test source file.
	* testsuite/ld-aarch64/copy-reloc-2.d: New test.
	* testsuite/ld-aarch64/copy-reloc-exe-eliminate.s: New test source file.
	* testsuite/ld-aarch64/copy-reloc-eliminate.d: New test.
	* testsuite/ld-aarch64/copy-reloc-so.s: Define new global objects.
	* testsuite/ld-aarch64/aarch64-elf.exp: Run new tests.
This commit is contained in:
Jiong Wang 2017-06-15 16:51:01 +01:00
parent 8cac017d35
commit 6353d82b8f
9 changed files with 220 additions and 47 deletions

View File

@ -1,3 +1,17 @@
2017-06-15 Jiong Wang <jiong.wang@arm.com>
PR ld/21532
* elfnn-aarch64.c (ELIMINATE_COPY_RELOCS): Set to 1.
(elfNN_aarch64_final_link_relocate): Also propagate relocations to
runtime for if there needs copy relocation elimination.
(need_copy_relocation_p): New function. Return true for symbol with
pc-relative references and if it's against read-only sections.
(elfNN_aarch64_adjust_dynamic_symbol): Use need_copy_relocation_p.
(elfNN_aarch64_check_relocs): Allocate dynrelocs for relocation types
that are related with accessing external objects.
(elfNN_aarch64_gc_sweep_hook): Sync the relocation types with the change
in elfNN_aarch64_check_relocs.
2017-06-15 Nick Clifton <nickc@redhat.com>
PR binutils/21582

View File

@ -249,7 +249,7 @@
|| (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC \
|| (R_TYPE) == BFD_RELOC_AARCH64_TLSDESC_OFF_G1)
#define ELIMINATE_COPY_RELOCS 0
#define ELIMINATE_COPY_RELOCS 1
/* Return size of a relocation entry. HTAB is the bfd's
elf_aarch64_link_hash_entry. */
@ -5169,12 +5169,25 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
/* When generating a shared object or relocatable executable, these
relocations are copied into the output file to be resolved at
run time. */
if ((bfd_link_pic (info)
|| globals->root.is_relocatable_executable)
&& (input_section->flags & SEC_ALLOC)
&& (h == NULL
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak))
if (((bfd_link_pic (info)
|| globals->root.is_relocatable_executable)
&& (input_section->flags & SEC_ALLOC)
&& (h == NULL
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak))
/* Or we are creating an executable, we may need to keep relocations
for symbols satisfied by a dynamic library if we manage to avoid
copy relocs for the symbol. */
|| (ELIMINATE_COPY_RELOCS
&& !bfd_link_pic (info)
&& h != NULL
&& (input_section->flags & SEC_ALLOC)
&& h->dynindx != -1
&& !h->non_got_ref
&& ((h->def_dynamic
&& !h->def_regular)
|| h->root.type == bfd_link_hash_undefweak
|| h->root.type == bfd_link_hash_undefined)))
{
Elf_Internal_Rela outrel;
bfd_byte *loc;
@ -6846,15 +6859,22 @@ elfNN_aarch64_gc_sweep_hook (bfd *abfd,
h->plt.refcount -= 1;
break;
case BFD_RELOC_AARCH64_ADD_LO12:
case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
case BFD_RELOC_AARCH64_LDST128_LO12:
case BFD_RELOC_AARCH64_LDST16_LO12:
case BFD_RELOC_AARCH64_LDST32_LO12:
case BFD_RELOC_AARCH64_LDST64_LO12:
case BFD_RELOC_AARCH64_LDST8_LO12:
case BFD_RELOC_AARCH64_LD_LO19_PCREL:
case BFD_RELOC_AARCH64_MOVW_G0_NC:
case BFD_RELOC_AARCH64_MOVW_G1_NC:
case BFD_RELOC_AARCH64_MOVW_G2_NC:
case BFD_RELOC_AARCH64_MOVW_G3:
case BFD_RELOC_AARCH64_NN:
if (h != NULL && bfd_link_executable (info))
if (h != NULL && !bfd_link_pic (info))
{
if (h->plt.refcount > 0)
h->plt.refcount -= 1;
@ -6869,6 +6889,31 @@ elfNN_aarch64_gc_sweep_hook (bfd *abfd,
return TRUE;
}
/* Return true if we need copy relocation against EH. */
static bfd_boolean
need_copy_relocation_p (struct elf_aarch64_link_hash_entry *eh)
{
struct elf_dyn_relocs *p;
asection *s;
for (p = eh->dyn_relocs; p != NULL; p = p->next)
{
/* If there is any pc-relative reference, we need to keep copy relocation
to avoid propagating the relocation into runtime that current glibc
does not support. */
if (p->pc_count)
return TRUE;
s = p->sec->output_section;
/* Need copy relocation if it's against read-only section. */
if (s != NULL && (s->flags & SEC_READONLY) != 0)
return TRUE;
}
return FALSE;
}
/* Adjust a symbol defined by a dynamic object and referenced by a
regular object. The current definition is in some section of the
dynamic object, but we're not including those sections. We have to
@ -6942,6 +6987,19 @@ elfNN_aarch64_adjust_dynamic_symbol (struct bfd_link_info *info,
return TRUE;
}
if (ELIMINATE_COPY_RELOCS)
{
struct elf_aarch64_link_hash_entry *eh;
/* If we didn't find any dynamic relocs in read-only sections, then
we'll be keeping the dynamic relocs and avoiding the copy reloc. */
eh = (struct elf_aarch64_link_hash_entry *) h;
if (!need_copy_relocation_p (eh))
{
h->non_got_ref = 0;
return TRUE;
}
}
/* We must allocate the symbol in our .dynbss section, which will
become part of the .bss section of the executable. There will be
an entry for this symbol in the .dynsym section. The dynamic
@ -7196,6 +7254,41 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
switch (bfd_r_type)
{
case BFD_RELOC_AARCH64_MOVW_G0_NC:
case BFD_RELOC_AARCH64_MOVW_G1_NC:
case BFD_RELOC_AARCH64_MOVW_G2_NC:
case BFD_RELOC_AARCH64_MOVW_G3:
if (bfd_link_pic (info))
{
int howto_index = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START;
_bfd_error_handler
/* xgettext:c-format */
(_("%B: relocation %s against `%s' can not be used when making "
"a shared object; recompile with -fPIC"),
abfd, elfNN_aarch64_howto_table[howto_index].name,
(h) ? h->root.root.string : "a local symbol");
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
/* Fall through. */
case BFD_RELOC_AARCH64_16_PCREL:
case BFD_RELOC_AARCH64_32_PCREL:
case BFD_RELOC_AARCH64_64_PCREL:
case BFD_RELOC_AARCH64_ADD_LO12:
case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
case BFD_RELOC_AARCH64_LDST128_LO12:
case BFD_RELOC_AARCH64_LDST16_LO12:
case BFD_RELOC_AARCH64_LDST32_LO12:
case BFD_RELOC_AARCH64_LDST64_LO12:
case BFD_RELOC_AARCH64_LDST8_LO12:
case BFD_RELOC_AARCH64_LD_LO19_PCREL:
if (h == NULL || bfd_link_pic (info))
break;
/* Fall through. */
case BFD_RELOC_AARCH64_NN:
/* We don't need to handle relocs into sections not going into
@ -7214,12 +7307,32 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
/* No need to do anything if we're not creating a shared
object. */
if (! bfd_link_pic (info))
if (!(bfd_link_pic (info)
/* If on the other hand, we are creating an executable, we
may need to keep relocations for symbols satisfied by a
dynamic library if we manage to avoid copy relocs for the
symbol.
NOTE: Currently, there is no support of copy relocs
elimination on pc-relative relocation types, because there is
no dynamic relocation support for them in glibc. We still
record the dynamic symbol reference for them. This is
because one symbol may be referenced by both absolute
relocation (for example, BFD_RELOC_AARCH64_NN) and
pc-relative relocation. We need full symbol reference
information to make correct decision later in
elfNN_aarch64_adjust_dynamic_symbol. */
|| (ELIMINATE_COPY_RELOCS
&& !bfd_link_pic (info)
&& h != NULL
&& (h->root.type == bfd_link_hash_defweak
|| !h->def_regular))))
break;
{
struct elf_dyn_relocs *p;
struct elf_dyn_relocs **head;
int howto_index = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START;
/* We must copy these reloc types into the output file.
Create a reloc section in dynobj and make room for
@ -7283,6 +7396,8 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
p->count += 1;
if (elfNN_aarch64_howto_table[howto_index].pc_relative)
p->pc_count += 1;
}
break;
@ -7386,44 +7501,6 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
break;
}
case BFD_RELOC_AARCH64_MOVW_G0_NC:
case BFD_RELOC_AARCH64_MOVW_G1_NC:
case BFD_RELOC_AARCH64_MOVW_G2_NC:
case BFD_RELOC_AARCH64_MOVW_G3:
if (bfd_link_pic (info))
{
int howto_index = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START;
_bfd_error_handler
/* xgettext:c-format */
(_("%B: relocation %s against `%s' can not be used when making "
"a shared object; recompile with -fPIC"),
abfd, elfNN_aarch64_howto_table[howto_index].name,
(h) ? h->root.root.string : "a local symbol");
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
/* Fall through. */
case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
if (h != NULL && bfd_link_executable (info))
{
/* If this reloc is in a read-only section, we might
need a copy reloc. We can't check reliably at this
stage whether the section is read-only, as input
sections have not yet been mapped to output sections.
Tentatively set the flag for now, and correct in
adjust_dynamic_symbol. */
h->non_got_ref = 1;
h->plt.refcount += 1;
h->pointer_equality_needed = 1;
}
/* FIXME:: RR need to handle these in shared libraries
and essentially bomb out as these being non-PIC
relocations in shared libraries. */
break;
case BFD_RELOC_AARCH64_CALL26:
case BFD_RELOC_AARCH64_JUMP26:
/* If this is a local symbol then we resolve it

View File

@ -1,3 +1,12 @@
2017-06-15 Jiong Wang <jiong.wang@arm.com>
* testsuite/ld-aarch64/copy-reloc-exe-2.s: New test source file.
* testsuite/ld-aarch64/copy-reloc-2.d: New test.
* testsuite/ld-aarch64/copy-reloc-exe-eliminate.s: New test source file.
* testsuite/ld-aarch64/copy-reloc-eliminate.d: New test.
* testsuite/ld-aarch64/copy-reloc-so.s: Define new global objects.
* testsuite/ld-aarch64/aarch64-elf.exp: Run new tests.
2017-06-14 Nick Clifton <nickc@redhat.com>
PR binutils/21580

View File

@ -335,6 +335,10 @@ set aarch64elflinktests {
{} "copy-reloc-so.so"}
{"ld-aarch64/exe with copy relocation" "-e0 tmpdir/copy-reloc-so.so" "" ""
{copy-reloc-exe.s} {{objdump -R copy-reloc.d}} "copy-reloc"}
{"ld-aarch64/exe with copy relocation 2" "-e0 tmpdir/copy-reloc-so.so" "" ""
{copy-reloc-exe-2.s} {{objdump -R copy-reloc-2.d}} "copy-reloc-2"}
{"ld-aarch64/exe with copy relocation elimination" "-e0 tmpdir/copy-reloc-so.so" "" ""
{copy-reloc-exe-eliminate.s} {{objdump -R copy-reloc-eliminate.d}} "copy-reloc-elimination"}
{"ld-aarch64/so with global func" "-shared" "" "" {func-in-so.s}
{} "func-in-so.so"}
{"ld-aarch64/func sym hash opt for exe"

View File

@ -0,0 +1,7 @@
.*
DYNAMIC RELOCATION RECORDS
OFFSET.*TYPE.*VALUE.*
.*R_AARCH64_COPY.*global_[abcd]
.*R_AARCH64_COPY.*global_[abcd]
.*R_AARCH64_COPY.*global_[abcd]
.*R_AARCH64_COPY.*global_[abcd]

View File

@ -0,0 +1,4 @@
.*
DYNAMIC RELOCATION RECORDS
OFFSET.*TYPE.*VALUE.*
.*R_AARCH64_ABS64.*global_a

View File

@ -0,0 +1,32 @@
# expect copy relocation for all these scenarios.
.global p
.global q
.global r
.section .data.rel.ro,"aw",%progbits
.align 3
.type p, %object
.size p, 8
p:
.xword global_a
.type q, %object
.size q, 8
q:
.xword global_b
.type r, %object
.size r, 8
r:
# Any pc-rel relocation as no dynamic linker support on AArch64.
.xword global_c - .
.text
.global main
main:
# Symbols are referenced by any other relocation against read-only
# section.
movz x0, :abs_g0_nc:global_a
adrp x1, global_b
# pc-rel.
adrp x2, global_d
add x2, x2, #:lo12:global_c

View File

@ -0,0 +1,7 @@
.global p
.section .data.rel.ro,"aw",%progbits
.align 3
.type p, %object
.size p, 8
p:
.xword global_a

View File

@ -1,6 +1,25 @@
.global global_a
.type global_a, %object
.size global_a, 4
.global global_b
.type global_b, %object
.size global_b, 4
.global global_c
.type global_c, %object
.size global_c, 4
.global global_d
.type global_d, %object
.size global_d, 4
.data
global_a:
.word 0xcafedead
global_b:
.word 0xcafecafe
global_c:
.word 0xdeadcafe
global_d:
.word 0xdeaddead