summaryrefslogtreecommitdiff
path: root/bfd/elfnn-aarch64.c
diff options
context:
space:
mode:
authormshawcroft <mshawcroft>2013-07-02 06:39:26 +0000
committermshawcroft <mshawcroft>2013-07-02 06:39:26 +0000
commite57aa58036314bfafcf8aef75c3d2cba38c69a9f (patch)
treef12ae055335fca480658cd1137fe9d9e78457c53 /bfd/elfnn-aarch64.c
parentf0b0486da05d22601f6c9174f5a5b240a37397f0 (diff)
downloadbinutils-redhat-e57aa58036314bfafcf8aef75c3d2cba38c69a9f.tar.gz
[AArch64] Fix creation of .got and placement of _GLOBAL_OFFSET_TABLE_
Diffstat (limited to 'bfd/elfnn-aarch64.c')
-rw-r--r--bfd/elfnn-aarch64.c91
1 files changed, 72 insertions, 19 deletions
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 1eda859e07..dcc6f27976 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -4647,6 +4647,70 @@ elfNN_aarch64_allocate_local_symbols (bfd *abfd, unsigned number)
return TRUE;
}
+/* Create the .got section to hold the global offset table. */
+
+static bfd_boolean
+aarch64_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
+{
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ flagword flags;
+ asection *s;
+ struct elf_link_hash_entry *h;
+ struct elf_link_hash_table *htab = elf_hash_table (info);
+
+ /* This function may be called more than once. */
+ s = bfd_get_linker_section (abfd, ".got");
+ if (s != NULL)
+ return TRUE;
+
+ flags = bed->dynamic_sec_flags;
+
+ s = bfd_make_section_anyway_with_flags (abfd,
+ (bed->rela_plts_and_copies_p
+ ? ".rela.got" : ".rel.got"),
+ (bed->dynamic_sec_flags
+ | SEC_READONLY));
+ if (s == NULL
+ || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+ return FALSE;
+ htab->srelgot = s;
+
+ s = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
+ if (s == NULL
+ || !bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
+ return FALSE;
+ htab->sgot = s;
+ htab->sgot->size += GOT_ENTRY_SIZE;
+
+ if (bed->want_got_sym)
+ {
+ /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
+ (or .got.plt) section. We don't do this in the linker script
+ because we don't want to define the symbol if we are not creating
+ a global offset table. */
+ h = _bfd_elf_define_linkage_sym (abfd, info, s,
+ "_GLOBAL_OFFSET_TABLE_");
+ elf_hash_table (info)->hgot = h;
+ if (h == NULL)
+ return FALSE;
+ }
+
+ if (bed->want_got_plt)
+ {
+ s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags);
+ if (s == NULL
+ || !bfd_set_section_alignment (abfd, s,
+ bed->s->log_file_align))
+ return FALSE;
+ htab->sgotplt = s;
+ }
+
+ /* The first bit of the global offset table is the header. */
+ s->size += bed->got_header_size;
+
+ return TRUE;
+}
+
/* Look through the relocs for a section during the first phase. */
static bfd_boolean
@@ -4880,14 +4944,10 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
}
}
- if (htab->root.sgot == NULL)
- {
- if (htab->root.dynobj == NULL)
- htab->root.dynobj = abfd;
- if (!_bfd_elf_create_got_section (htab->root.dynobj, info))
- return FALSE;
- htab->root.sgot->size += GOT_ENTRY_SIZE;
- }
+ if (htab->root.dynobj == NULL)
+ htab->root.dynobj = abfd;
+ if (! aarch64_elf_create_got_section (htab->root.dynobj, info))
+ return FALSE;
break;
}
@@ -5481,7 +5541,10 @@ elfNN_aarch64_create_dynamic_sections (bfd *dynobj,
struct bfd_link_info *info)
{
struct elf_aarch64_link_hash_table *htab;
- struct elf_link_hash_entry *h;
+
+ /* We need to create .got section. */
+ if (!aarch64_elf_create_got_section (dynobj, info))
+ return FALSE;
if (!_bfd_elf_create_dynamic_sections (dynobj, info))
return FALSE;
@@ -5494,16 +5557,6 @@ elfNN_aarch64_create_dynamic_sections (bfd *dynobj,
if (!htab->sdynbss || (!info->shared && !htab->srelbss))
abort ();
- /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the
- dynobj's .got section. We don't do this in the linker script
- because we don't want to define the symbol if we are not creating
- a global offset table. */
- h = _bfd_elf_define_linkage_sym (dynobj, info,
- htab->root.sgot, "_GLOBAL_OFFSET_TABLE_");
- elf_hash_table (info)->hgot = h;
- if (h == NULL)
- return FALSE;
-
return TRUE;
}