aboutsummaryrefslogtreecommitdiff
path: root/bfd/elfnn-aarch64.c
diff options
context:
space:
mode:
authorJiong Wang <jiong.wang@arm.com>2017-06-15 16:51:01 +0100
committerJiong Wang <jiong.wang@arm.com>2017-06-15 17:04:04 +0100
commit6353d82b8fa825c2143f41e84b0d5d4446c6e99a (patch)
tree8acf1add319d0c4c3775adbcd3faeb7aa65429e1 /bfd/elfnn-aarch64.c
parent8cac017d35ef374e65acc98818a17cf8a652cbd0 (diff)
downloadgdb-6353d82b8fa825c2143f41e84b0d5d4446c6e99a.zip
gdb-6353d82b8fa825c2143f41e84b0d5d4446c6e99a.tar.gz
gdb-6353d82b8fa825c2143f41e84b0d5d4446c6e99a.tar.bz2
[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.
Diffstat (limited to 'bfd/elfnn-aarch64.c')
-rw-r--r--bfd/elfnn-aarch64.c171
1 files changed, 124 insertions, 47 deletions
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 1edf2a0..e27f067 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -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