X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=ld%2Fldelf.c;h=8f2167e8895ef3bdd5029ff2f5c247ad868c3617;hb=196535a69c8568342e62fdf5e3f5ade04470fd6a;hp=3b0f3ada8c2b9518d6689f5c103c5aff85374bee;hpb=0aa0727c8fe337cbe3319f01afc6e6afb16820aa;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/ldelf.c b/ld/ldelf.c index 3b0f3ada8c..8f2167e889 100644 --- a/ld/ldelf.c +++ b/ld/ldelf.c @@ -1,5 +1,5 @@ /* ELF emulation code for targets using elf.em. - Copyright (C) 1991-2019 Free Software Foundation, Inc. + Copyright (C) 1991-2020 Free Software Foundation, Inc. This file is part of the GNU Binutils. @@ -23,6 +23,8 @@ #include "libiberty.h" #include "filenames.h" #include "safe-ctype.h" +#include "bfdlink.h" +#include "ctf-api.h" #include "ld.h" #include "ldmain.h" #include "ldmisc.h" @@ -373,6 +375,9 @@ ldelf_try_needed (struct dt_needed *needed, int force, int is_linux) bfd_elf_set_dyn_lib_class (abfd, (enum dynamic_lib_link_class) link_class); + *link_info.input_bfds_tail = abfd; + link_info.input_bfds_tail = &abfd->link.next; + /* Add this file into the symbol table. */ if (! bfd_link_add_symbols (abfd, &link_info)) einfo (_("%F%P: %pB: error adding symbols: %E\n"), abfd); @@ -778,8 +783,7 @@ ldelf_parse_ld_so_conf_include (struct ldelf_ld_so_conf *info, ldelf_parse_ld_so_conf (info, pattern); #endif - if (newp) - free (newp); + free (newp); } static bfd_boolean @@ -892,7 +896,7 @@ ldelf_parse_ld_so_conf (struct ldelf_ld_so_conf *info, const char *filename) static bfd_boolean ldelf_check_ld_so_conf (const struct bfd_link_needed_list *l, int force, - int elfsize) + int elfsize, const char *prefix) { static bfd_boolean initialized; static const char *ld_so_conf; @@ -905,7 +909,7 @@ ldelf_check_ld_so_conf (const struct bfd_link_needed_list *l, int force, info.path = NULL; info.len = info.alloc = 0; - tmppath = concat (ld_sysroot, "${prefix}/etc/ld.so.conf", + tmppath = concat (ld_sysroot, prefix, "/etc/ld.so.conf", (const char *) NULL); if (!ldelf_parse_ld_so_conf (&info, tmppath)) { @@ -984,12 +988,13 @@ ldelf_check_needed (lang_input_statement_type *s) void ldelf_after_open (int use_libpath, int native, int is_linux, int is_freebsd, - int elfsize) + 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 (); @@ -1018,7 +1023,7 @@ ldelf_after_open (int use_libpath, int native, int is_linux, int is_freebsd, abfd != (bfd *) NULL; abfd = abfd->link.next) if (bfd_get_flavour (abfd) == bfd_target_elf_flavour && bfd_count_sections (abfd) != 0 - && !((lang_input_statement_type *) abfd->usrdata)->flags.just_syms) + && !bfd_input_just_syms (abfd)) break; /* PR 10555: If there are no ELF input files do not try to @@ -1033,6 +1038,17 @@ ldelf_after_open (int use_libpath, int native, int is_linux, int is_freebsd, 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) + { + if (elf_tdata (abfd) != NULL + && elf_tdata (abfd)->elf_header != NULL + /* FIXME: Maybe check for other non-supportable types as well ? */ + && elf_tdata (abfd)->elf_header->e_type == ET_EXEC) + 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) @@ -1049,7 +1065,7 @@ ldelf_after_open (int use_libpath, int native, int is_linux, int is_freebsd, } return; } - + if (!link_info.traditional_format) { bfd *elfbfd = NULL; @@ -1060,12 +1076,19 @@ ldelf_after_open (int use_libpath, int native, int is_linux, int is_freebsd, { int type = 0; - if (((lang_input_statement_type *) abfd->usrdata)->flags.just_syms) + if (bfd_link_executable (& link_info) + && elf_tdata (abfd)->elf_header->e_type == ET_EXEC) + { + einfo (_("%F%P: cannot use executable file '%pB' as input to a link\n"), + abfd); + } + + if (bfd_input_just_syms (abfd)) continue; for (s = abfd->sections; s && type < COMPACT_EH_HDR; s = s->next) { - const char *name = bfd_get_section_name (abfd, s); + const char *name = bfd_section_name (s); if (bfd_is_abs_section (s->output_section)) continue; @@ -1112,7 +1135,7 @@ ldelf_after_open (int use_libpath, int native, int is_linux, int is_freebsd, bed->dynamic_sec_flags | SEC_READONLY); if (s != NULL - && bfd_set_section_alignment (elfbfd, s, 2)) + && bfd_set_section_alignment (s, 2)) { htab->eh_info.hdr_sec = s; warn_eh_frame = FALSE; @@ -1132,6 +1155,7 @@ ldelf_after_open (int use_libpath, int native, int is_linux, int is_freebsd, special action by the person doing the link. Note that the needed list can actually grow while we are stepping through this loop. */ + save_input_bfd_tail = link_info.input_bfds_tail; needed = bfd_elf_get_needed_list (link_info.output_bfd, &link_info); for (l = needed; l != NULL; l = l->next) { @@ -1258,7 +1282,7 @@ ldelf_after_open (int use_libpath, int native, int is_linux, int is_freebsd, break; if (is_linux - && ldelf_check_ld_so_conf (l, force, elfsize)) + && ldelf_check_ld_so_conf (l, force, elfsize, prefix)) break; } @@ -1288,6 +1312,20 @@ 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")); + } + + link_info.input_bfds_tail = save_input_bfd_tail; + *save_input_bfd_tail = NULL; + 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")); @@ -1382,7 +1420,7 @@ ldelf_setup_build_id (bfd *ibfd) flags = (SEC_ALLOC | SEC_LOAD | SEC_IN_MEMORY | SEC_LINKER_CREATED | SEC_READONLY | SEC_DATA); s = bfd_make_section_with_flags (ibfd, ".note.gnu.build-id", flags); - if (s != NULL && bfd_set_section_alignment (ibfd, s, 2)) + if (s != NULL && bfd_set_section_alignment (s, 2)) { struct elf_obj_tdata *t = elf_tdata (link_info.output_bfd); t->o->build_id.after_write_object_contents = &write_build_id; @@ -1778,7 +1816,7 @@ output_rel_find (int isdyn, int rela) lang_output_section_statement_type *last_rel = NULL; lang_output_section_statement_type *last_rel_alloc = NULL; - for (lookup = &lang_os_list.head->output_section_statement; + for (lookup = (void *) lang_os_list.head; lookup != NULL; lookup = lookup->next) { @@ -1844,13 +1882,13 @@ elf_orphan_compatible (asection *in, asection *out) if (elf_section_data (out)->this_hdr.sh_info != elf_section_data (in)->this_hdr.sh_info) return FALSE; - /* We can't merge with member of output section group nor merge two - sections with differing SHF_EXCLUDE when doing a relocatable link. - */ + /* We can't merge with a member of an output section group or merge + two sections with differing SHF_EXCLUDE or other processor and OS + specific flags when doing a relocatable link. */ if (bfd_link_relocatable (&link_info) && (elf_next_in_group (out) != NULL || ((elf_section_flags (out) ^ elf_section_flags (in)) - & SHF_EXCLUDE) != 0)) + & (SHF_MASKPROC | SHF_MASKOS)) != 0)) return FALSE; return _bfd_elf_match_sections_by_type (link_info.output_bfd, out, in->owner, in); @@ -1950,7 +1988,7 @@ ldelf_place_orphan (asection *s, const char *secname, int constraint) { /* Find the output mbind section with the same type, attributes and sh_info field. */ - for (os = &lang_os_list.head->output_section_statement; + for (os = (void *) lang_os_list.head; os != NULL; os = os->next) if (os->bfd_section != NULL @@ -2065,9 +2103,7 @@ ldelf_place_orphan (asection *s, const char *secname, int constraint) && (nexts->flags & SEC_EXCLUDE) == 0 && ((nexts->flags ^ flags) & (SEC_LOAD | SEC_ALLOC)) == 0 && (nexts->owner->flags & DYNAMIC) == 0 - && nexts->owner->usrdata != NULL - && !(((lang_input_statement_type *) nexts->owner->usrdata) - ->flags.just_syms) + && !bfd_input_just_syms (nexts->owner) && _bfd_elf_match_sections_by_type (nexts->owner, nexts, s->owner, s)) flags = (((flags ^ SEC_READONLY) @@ -2129,8 +2165,37 @@ ldelf_place_orphan (asection *s, const char *secname, int constraint) _bfd_elf_match_sections_by_type); if (after == NULL) /* *ABS* is always the first output section statement. */ - after = &lang_os_list.head->output_section_statement; + after = (void *) lang_os_list.head; } return lang_insert_orphan (s, secname, constraint, after, place, NULL, NULL); } + +void +ldelf_before_place_orphans (void) +{ + bfd *abfd; + + 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)) + { + asection *isec; + for (isec = abfd->sections; isec != NULL; isec = isec->next) + { + /* Discard a section if any of its linked-to section has + been discarded. */ + asection *linked_to_sec; + for (linked_to_sec = elf_linked_to_section (isec); + linked_to_sec != NULL; + linked_to_sec = elf_linked_to_section (linked_to_sec)) + if (discarded_section (linked_to_sec)) + { + isec->output_section = bfd_abs_section_ptr; + break; + } + } + } +}