summaryrefslogtreecommitdiff
path: root/ld/ldelf.c
diff options
context:
space:
mode:
Diffstat (limited to 'ld/ldelf.c')
-rw-r--r--ld/ldelf.c411
1 files changed, 228 insertions, 183 deletions
diff --git a/ld/ldelf.c b/ld/ldelf.c
index d15f027e91a..4094640b3f7 100644
--- a/ld/ldelf.c
+++ b/ld/ldelf.c
@@ -71,10 +71,26 @@ ldelf_after_parse (void)
einfo (_("%P: warning: -z dynamic-undefined-weak ignored\n"));
link_info.dynamic_undefined_weak = 0;
}
+
+ /* Disable DT_RELR if not building PIE nor shared library. */
+ if (!bfd_link_pic (&link_info))
+ link_info.enable_dt_relr = 0;
+
+ /* Add 3 spare tags for DT_RELR, DT_RELRSZ and DT_RELRENT. */
+ if (link_info.enable_dt_relr)
+ link_info.spare_dynamic_tags += 3;
+
after_parse_default ();
if (link_info.commonpagesize > link_info.maxpagesize)
- einfo (_("%F%P: common page size (0x%v) > maximum page size (0x%v)\n"),
- link_info.commonpagesize, link_info.maxpagesize);
+ {
+ if (!link_info.commonpagesize_is_set)
+ link_info.commonpagesize = link_info.maxpagesize;
+ else if (!link_info.maxpagesize_is_set)
+ link_info.maxpagesize = link_info.commonpagesize;
+ else
+ einfo (_("%F%P: common page size (0x%v) > maximum page size (0x%v)\n"),
+ link_info.commonpagesize, link_info.maxpagesize);
+ }
}
/* Handle the generation of DT_NEEDED tags. */
@@ -989,173 +1005,15 @@ ldelf_check_needed (lang_input_statement_type *s)
}
}
-/* This is called after all the input files have been opened. */
-
-void
-ldelf_after_open (int use_libpath, int native, int is_linux, int is_freebsd,
- int elfsize, const char *prefix)
+static void
+ldelf_handle_dt_needed (struct elf_link_hash_table *htab,
+ int use_libpath, int native, int is_linux,
+ int is_freebsd, int elfsize, const char *prefix)
{
struct bfd_link_needed_list *needed, *l;
- struct elf_link_hash_table *htab;
- asection *s;
bfd *abfd;
bfd **save_input_bfd_tail;
- after_open_default ();
-
- htab = elf_hash_table (&link_info);
- if (!is_elf_hash_table (&htab->root))
- return;
-
- if (command_line.out_implib_filename)
- {
- unlink_if_ordinary (command_line.out_implib_filename);
- link_info.out_implib_bfd
- = bfd_openw (command_line.out_implib_filename,
- bfd_get_target (link_info.output_bfd));
-
- if (link_info.out_implib_bfd == NULL)
- {
- einfo (_("%F%P: %s: can't open for writing: %E\n"),
- command_line.out_implib_filename);
- }
- }
-
- if (ldelf_emit_note_gnu_build_id != NULL)
- {
- /* Find an ELF input. */
- for (abfd = link_info.input_bfds;
- abfd != (bfd *) NULL; abfd = abfd->link.next)
- if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
- && bfd_count_sections (abfd) != 0
- && !bfd_input_just_syms (abfd))
- break;
-
- /* PR 10555: If there are no ELF input files do not try to
- create a .note.gnu-build-id section. */
- if (abfd == NULL
- || !ldelf_setup_build_id (abfd))
- {
- free ((char *) ldelf_emit_note_gnu_build_id);
- ldelf_emit_note_gnu_build_id = NULL;
- }
- }
-
- get_elf_backend_data (link_info.output_bfd)->setup_gnu_properties (&link_info);
-
- /* Do not allow executable files to be used as inputs to the link. */
- for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)
- {
- /* Discard input .note.gnu.build-id sections. */
- s = bfd_get_section_by_name (abfd, ".note.gnu.build-id");
- while (s != NULL)
- {
- if (s != elf_tdata (link_info.output_bfd)->o->build_id.sec)
- s->flags |= SEC_EXCLUDE;
- s = bfd_get_next_section_by_name (NULL, s);
- }
-
- if (abfd->xvec->flavour == bfd_target_elf_flavour
- && !bfd_input_just_syms (abfd)
- && elf_tdata (abfd) != NULL
- /* FIXME: Maybe check for other non-supportable types as well ? */
- && (elf_tdata (abfd)->elf_header->e_type == ET_EXEC
- || (elf_tdata (abfd)->elf_header->e_type == ET_DYN
- && elf_tdata (abfd)->is_pie)))
- einfo (_("%F%P: cannot use executable file '%pB' as input to a link\n"),
- abfd);
- }
-
- if (bfd_link_relocatable (&link_info))
- {
- if (link_info.execstack == !link_info.noexecstack)
- {
- /* PR ld/16744: If "-z [no]execstack" has been specified on the
- command line and we are perfoming a relocatable link then no
- PT_GNU_STACK segment will be created and so the
- linkinfo.[no]execstack values set in _handle_option() will have no
- effect. Instead we create a .note.GNU-stack section in much the
- same way as the assembler does with its --[no]execstack option. */
- flagword flags = SEC_READONLY | (link_info.execstack ? SEC_CODE : 0);
- (void) bfd_make_section_with_flags (link_info.input_bfds,
- ".note.GNU-stack", flags);
- }
- return;
- }
-
- if (!link_info.traditional_format)
- {
- bfd *elfbfd = NULL;
- bool warn_eh_frame = false;
- int seen_type = 0;
-
- for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)
- {
- int type = 0;
-
- if (bfd_input_just_syms (abfd))
- continue;
-
- for (s = abfd->sections; s && type < COMPACT_EH_HDR; s = s->next)
- {
- const char *name = bfd_section_name (s);
-
- if (bfd_is_abs_section (s->output_section))
- continue;
- if (startswith (name, ".eh_frame_entry"))
- type = COMPACT_EH_HDR;
- else if (strcmp (name, ".eh_frame") == 0 && s->size > 8)
- type = DWARF2_EH_HDR;
- }
-
- if (type != 0)
- {
- if (seen_type == 0)
- {
- seen_type = type;
- }
- else if (seen_type != type)
- {
- einfo (_("%F%P: compact frame descriptions incompatible with"
- " DWARF2 .eh_frame from %pB\n"),
- type == DWARF2_EH_HDR ? abfd : elfbfd);
- break;
- }
-
- if (!elfbfd
- && (type == COMPACT_EH_HDR
- || link_info.eh_frame_hdr_type != 0))
- {
- if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
- elfbfd = abfd;
-
- warn_eh_frame = true;
- }
- }
-
- if (seen_type == COMPACT_EH_HDR)
- link_info.eh_frame_hdr_type = COMPACT_EH_HDR;
- }
- if (elfbfd)
- {
- const struct elf_backend_data *bed;
-
- bed = get_elf_backend_data (elfbfd);
- s = bfd_make_section_with_flags (elfbfd, ".eh_frame_hdr",
- bed->dynamic_sec_flags
- | SEC_READONLY);
- if (s != NULL
- && bfd_set_section_alignment (s, 2))
- {
- htab->eh_info.hdr_sec = s;
- warn_eh_frame = false;
- }
- }
- if (warn_eh_frame)
- einfo (_("%P: warning: cannot create .eh_frame_hdr section,"
- " --eh-frame-hdr ignored\n"));
- }
-
/* Get the list of files which appear in DT_NEEDED entries in
dynamic objects included in the link (often there will be none).
For each such file, we want to track down the corresponding
@@ -1179,10 +1037,12 @@ ldelf_after_open (int use_libpath, int native, int is_linux, int is_freebsd,
&& (bfd_elf_get_dyn_lib_class (l->by) & DYN_AS_NEEDED) != 0)
continue;
- /* Skip the lib if --no-copy-dt-needed-entries and
- --allow-shlib-undefined is in effect. */
+ /* Skip the lib if --no-copy-dt-needed-entries and when we are
+ handling DT_NEEDED entries or --allow-shlib-undefined is in
+ effect. */
if (l->by != NULL
- && link_info.unresolved_syms_in_shared_libs == RM_IGNORE
+ && (htab->handling_dt_needed
+ || link_info.unresolved_syms_in_shared_libs == RM_IGNORE)
&& (bfd_elf_get_dyn_lib_class (l->by) & DYN_NO_ADD_NEEDED) != 0)
continue;
@@ -1322,23 +1182,214 @@ ldelf_after_open (int use_libpath, int native, int is_linux, int is_freebsd,
l->name, l->by);
}
- for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)
- if (bfd_get_format (abfd) == bfd_object
- && ((abfd->flags) & DYNAMIC) != 0
- && bfd_get_flavour (abfd) == bfd_target_elf_flavour
- && (elf_dyn_lib_class (abfd) & (DYN_AS_NEEDED | DYN_NO_NEEDED)) == 0
- && elf_dt_name (abfd) != NULL)
- {
- if (bfd_elf_add_dt_needed_tag (abfd, &link_info) < 0)
- einfo (_("%F%P: failed to add DT_NEEDED dynamic tag\n"));
- }
+ /* Don't add DT_NEEDED when loading shared objects from DT_NEEDED for
+ plugin symbol resolution while handling DT_NEEDED entries. */
+ if (!htab->handling_dt_needed)
+ for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)
+ if (bfd_get_format (abfd) == bfd_object
+ && ((abfd->flags) & DYNAMIC) != 0
+ && bfd_get_flavour (abfd) == bfd_target_elf_flavour
+ && (elf_dyn_lib_class (abfd) & (DYN_AS_NEEDED | DYN_NO_NEEDED)) == 0
+ && elf_dt_name (abfd) != NULL)
+ {
+ if (bfd_elf_add_dt_needed_tag (abfd, &link_info) < 0)
+ einfo (_("%F%P: failed to add DT_NEEDED dynamic tag\n"));
+ }
link_info.input_bfds_tail = save_input_bfd_tail;
*save_input_bfd_tail = NULL;
+}
+
+/* This is called before calling plugin 'all symbols read' hook. */
+
+void
+ldelf_before_plugin_all_symbols_read (int use_libpath, int native,
+ int is_linux, int is_freebsd,
+ int elfsize, const char *prefix)
+{
+ struct elf_link_hash_table *htab = elf_hash_table (&link_info);
+
+ if (!is_elf_hash_table (&htab->root))
+ return;
+
+ htab->handling_dt_needed = true;
+ ldelf_handle_dt_needed (htab, use_libpath, native, is_linux,
+ is_freebsd, elfsize, prefix);
+ htab->handling_dt_needed = false;
+}
+
+/* This is called after all the input files have been opened and all
+ symbols have been loaded. */
+
+void
+ldelf_after_open (int use_libpath, int native, int is_linux, int is_freebsd,
+ int elfsize, const char *prefix)
+{
+ struct elf_link_hash_table *htab;
+ asection *s;
+ bfd *abfd;
+
+ after_open_default ();
+
+ htab = elf_hash_table (&link_info);
+ if (!is_elf_hash_table (&htab->root))
+ return;
+
+ if (command_line.out_implib_filename)
+ {
+ unlink_if_ordinary (command_line.out_implib_filename);
+ link_info.out_implib_bfd
+ = bfd_openw (command_line.out_implib_filename,
+ bfd_get_target (link_info.output_bfd));
+
+ if (link_info.out_implib_bfd == NULL)
+ {
+ einfo (_("%F%P: %s: can't open for writing: %E\n"),
+ command_line.out_implib_filename);
+ }
+ }
+
+ if (ldelf_emit_note_gnu_build_id != NULL)
+ {
+ /* Find an ELF input. */
+ for (abfd = link_info.input_bfds;
+ abfd != (bfd *) NULL; abfd = abfd->link.next)
+ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+ && bfd_count_sections (abfd) != 0
+ && !bfd_input_just_syms (abfd))
+ break;
+
+ /* PR 10555: If there are no ELF input files do not try to
+ create a .note.gnu-build-id section. */
+ if (abfd == NULL
+ || !ldelf_setup_build_id (abfd))
+ {
+ free ((char *) ldelf_emit_note_gnu_build_id);
+ ldelf_emit_note_gnu_build_id = NULL;
+ }
+ }
+
+ get_elf_backend_data (link_info.output_bfd)->setup_gnu_properties (&link_info);
+
+ /* Do not allow executable files to be used as inputs to the link. */
+ for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)
+ {
+ /* Discard input .note.gnu.build-id sections. */
+ s = bfd_get_section_by_name (abfd, ".note.gnu.build-id");
+ while (s != NULL)
+ {
+ if (s != elf_tdata (link_info.output_bfd)->o->build_id.sec)
+ s->flags |= SEC_EXCLUDE;
+ s = bfd_get_next_section_by_name (NULL, s);
+ }
+
+ if (abfd->xvec->flavour == bfd_target_elf_flavour
+ && !bfd_input_just_syms (abfd)
+ && elf_tdata (abfd) != NULL
+ /* FIXME: Maybe check for other non-supportable types as well ? */
+ && (elf_tdata (abfd)->elf_header->e_type == ET_EXEC
+ || (elf_tdata (abfd)->elf_header->e_type == ET_DYN
+ && elf_tdata (abfd)->is_pie)))
+ einfo (_("%F%P: cannot use executable file '%pB' as input to a link\n"),
+ abfd);
+ }
+
+ if (bfd_link_relocatable (&link_info))
+ {
+ if (link_info.execstack == !link_info.noexecstack)
+ {
+ /* PR ld/16744: If "-z [no]execstack" has been specified on the
+ command line and we are perfoming a relocatable link then no
+ PT_GNU_STACK segment will be created and so the
+ linkinfo.[no]execstack values set in _handle_option() will have no
+ effect. Instead we create a .note.GNU-stack section in much the
+ same way as the assembler does with its --[no]execstack option. */
+ flagword flags = SEC_READONLY | (link_info.execstack ? SEC_CODE : 0);
+ (void) bfd_make_section_with_flags (link_info.input_bfds,
+ ".note.GNU-stack", flags);
+ }
+ return;
+ }
+
+ if (!link_info.traditional_format)
+ {
+ bfd *elfbfd = NULL;
+ bool warn_eh_frame = false;
+ int seen_type = 0;
+
+ for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)
+ {
+ int type = 0;
+
+ if (bfd_input_just_syms (abfd))
+ continue;
+
+ for (s = abfd->sections; s && type < COMPACT_EH_HDR; s = s->next)
+ {
+ const char *name = bfd_section_name (s);
+
+ if (bfd_is_abs_section (s->output_section))
+ continue;
+ if (startswith (name, ".eh_frame_entry"))
+ type = COMPACT_EH_HDR;
+ else if (strcmp (name, ".eh_frame") == 0 && s->size > 8)
+ type = DWARF2_EH_HDR;
+ }
+
+ if (type != 0)
+ {
+ if (seen_type == 0)
+ {
+ seen_type = type;
+ }
+ else if (seen_type != type)
+ {
+ einfo (_("%F%P: compact frame descriptions incompatible with"
+ " DWARF2 .eh_frame from %pB\n"),
+ type == DWARF2_EH_HDR ? abfd : elfbfd);
+ break;
+ }
+
+ if (!elfbfd
+ && (type == COMPACT_EH_HDR
+ || link_info.eh_frame_hdr_type != 0))
+ {
+ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
+ elfbfd = abfd;
+
+ warn_eh_frame = true;
+ }
+ }
+
+ if (seen_type == COMPACT_EH_HDR)
+ link_info.eh_frame_hdr_type = COMPACT_EH_HDR;
+ }
+ if (elfbfd)
+ {
+ const struct elf_backend_data *bed;
+
+ bed = get_elf_backend_data (elfbfd);
+ s = bfd_make_section_with_flags (elfbfd, ".eh_frame_hdr",
+ bed->dynamic_sec_flags
+ | SEC_READONLY);
+ if (s != NULL
+ && bfd_set_section_alignment (s, 2))
+ {
+ htab->eh_info.hdr_sec = s;
+ warn_eh_frame = false;
+ }
+ }
+ if (warn_eh_frame)
+ einfo (_("%P: warning: cannot create .eh_frame_hdr section,"
+ " --eh-frame-hdr ignored\n"));
+ }
if (link_info.eh_frame_hdr_type == COMPACT_EH_HDR)
if (!bfd_elf_parse_eh_frame_entries (NULL, &link_info))
einfo (_("%F%P: failed to parse EH frame entries\n"));
+
+ ldelf_handle_dt_needed (htab, use_libpath, native, is_linux,
+ is_freebsd, elfsize, prefix);
}
static bfd_size_type
@@ -1591,11 +1642,6 @@ ldelf_before_allocation (char *audit, char *depaudit,
|| h->root.type == bfd_link_hash_undefweak
|| h->root.type == bfd_link_hash_common))
{
- const struct elf_backend_data *bed;
- bed = get_elf_backend_data (link_info.output_bfd);
- (*bed->elf_backend_hide_symbol) (&link_info, h, true);
- if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
- h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
/* Don't leave the symbol undefined. Undefined hidden
symbols typically won't have dynamic relocations, but
we most likely will need dynamic relocations for
@@ -1608,7 +1654,6 @@ ldelf_before_allocation (char *audit, char *depaudit,
sizeof ehdr_start_save_u);
ehdr_start->type = bfd_link_hash_defined;
/* It will be converted to section-relative later. */
- ehdr_start->rel_from_abs = 1;
ehdr_start->u.def.section = bfd_abs_section_ptr;
ehdr_start->u.def.value = 0;
}