diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 1edf2a0..e27f067 100644 (file)
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -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
diff --git a/ld/testsuite/ld-aarch64/copy-reloc-2.d b/ld/testsuite/ld-aarch64/copy-reloc-2.d
new file mode 100644 (file)
index 0000000..87ddccd
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/copy-reloc-2.d
@@ -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]
diff --git a/ld/testsuite/ld-aarch64/copy-reloc-eliminate.d b/ld/testsuite/ld-aarch64/copy-reloc-eliminate.d
new file mode 100644 (file)
index 0000000..9657d65
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/copy-reloc-eliminate.d
@@ -0,0 +1,4 @@
+.*
+DYNAMIC RELOCATION RECORDS
+OFFSET.*TYPE.*VALUE.*
+.*R_AARCH64_ABS64.*global_a
diff --git a/ld/testsuite/ld-aarch64/copy-reloc-exe-2.s b/ld/testsuite/ld-aarch64/copy-reloc-exe-2.s
new file mode 100644 (file)
index 0000000..d83658c
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/copy-reloc-exe-2.s
@@ -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
diff --git a/ld/testsuite/ld-aarch64/copy-reloc-exe-eliminate.s b/ld/testsuite/ld-aarch64/copy-reloc-exe-eliminate.s
new file mode 100644 (file)
index 0000000..33227aa
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/copy-reloc-exe-eliminate.s
@@ -0,0 +1,7 @@
+ .global p
+ .section .data.rel.ro,"aw",%progbits
+ .align 3
+ .type p, %object
+ .size p, 8
+p:
+ .xword global_a
--- binutils.orig/ld/testsuite/ld-aarch64/copy-reloc-so.s 2017-10-10 16:56:06.347550451 +0100
+++ binutils-2.27/ld/testsuite/ld-aarch64/copy-reloc-so.s 2017-10-10 16:56:25.926321182 +0100
@@ -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
--- binutils.orig/ld/testsuite/ld-aarch64/aarch64-elf.exp 2017-10-10 16:56:06.347550451 +0100
+++ binutils-2.27/ld/testsuite/ld-aarch64/aarch64-elf.exp 2017-10-10 16:58:19.629989701 +0100
@@ -292,6 +292,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"}
}
run_ld_link_tests $aarch64elflinktests
--- binutils.orig/bfd/elfnn-aarch64.c 2017-10-10 16:56:05.783557056 +0100
+++ binutils-2.27/bfd/elfnn-aarch64.c 2017-10-10 17:15:02.559298576 +0100
@@ -246,7 +246,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. */
@@ -5154,12 +5154,25 @@ elfNN_aarch64_final_link_relocate (reloc
/* 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) == TRUE)
- || 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) == TRUE)
+ || 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;
@@ -6777,15 +6790,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;
@@ -7158,6 +7178,41 @@ elfNN_aarch64_check_relocs (bfd *abfd, s
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
@@ -7176,12 +7231,32 @@ elfNN_aarch64_check_relocs (bfd *abfd, s
/* No need to do anything if we're not creating a shared
object. */
- if (! bfd_link_pic (info))
- break;
+ 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
@@ -7245,6 +7320,8 @@ elfNN_aarch64_check_relocs (bfd *abfd, s
p->count += 1;
+ if (elfNN_aarch64_howto_table[howto_index].pc_relative)
+ p->pc_count += 1;
}
break;
@@ -7348,42 +7425,6 @@ elfNN_aarch64_check_relocs (bfd *abfd, s
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)
- (_("%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;
- }
-
- 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