You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
367 lines
13 KiB
367 lines
13 KiB
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
|
|
|