diff options
Diffstat (limited to 'ld/ldlang.c')
-rw-r--r-- | ld/ldlang.c | 66 |
1 files changed, 43 insertions, 23 deletions
diff --git a/ld/ldlang.c b/ld/ldlang.c index 0bb9e17..6e31c35 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -43,6 +43,7 @@ #include "hashtab.h" #include "elf-bfd.h" #include "bfdver.h" +#include <errno.h> #if BFD_SUPPORTS_PLUGINS #include "plugin.h" @@ -322,7 +323,7 @@ spec_match (const struct wildcard_spec *spec, const char *name) } static char * -ldirname (const char *name) +stat_ldirname (const char *name) { const char *base = lbasename (name); @@ -1266,7 +1267,7 @@ new_afile (const char *name, /* If name is a relative path, search the directory of the current linker script first. */ if (from_filename && !IS_ABSOLUTE_PATH (name)) - p->extra_search_path = ldirname (from_filename); + p->extra_search_path = stat_ldirname (from_filename); p->flags.real = true; p->flags.search_dirs = true; break; @@ -2486,11 +2487,18 @@ lang_map (void) } static bool +is_defined (struct bfd_link_hash_entry *h) +{ + return h != NULL + && (h->type == bfd_link_hash_defined + || h->type == bfd_link_hash_defweak); +} + +static bool sort_def_symbol (struct bfd_link_hash_entry *hash_entry, void *info ATTRIBUTE_UNUSED) { - if ((hash_entry->type == bfd_link_hash_defined - || hash_entry->type == bfd_link_hash_defweak) + if (is_defined (hash_entry) && hash_entry->u.def.section->owner != link_info.output_bfd && hash_entry->u.def.section->owner != NULL) { @@ -2867,7 +2875,7 @@ lang_add_section (lang_statement_list_type *ptr, /* This must happen after flags have been updated. The output section may have been created before we saw its first input section, eg. for a data statement. */ - bfd_init_private_section_data (section->owner, section, + bfd_copy_private_section_data (section->owner, section, link_info.output_bfd, output->bfd_section, &link_info); @@ -4184,9 +4192,7 @@ ldlang_check_require_defined_symbols (void) h = bfd_link_hash_lookup (link_info.hash, ptr->name, false, false, true); - if (h == NULL - || (h->type != bfd_link_hash_defined - && h->type != bfd_link_hash_defweak)) + if (! is_defined (h)) einfo(_("%X%P: required symbol `%s' not defined\n"), ptr->name); } } @@ -4892,9 +4898,7 @@ print_assignment (lang_assignment_statement_type *assignment, h = bfd_link_hash_lookup (link_info.hash, assignment->exp->assign.dst, false, false, true); - if (h != NULL - && (h->type == bfd_link_hash_defined - || h->type == bfd_link_hash_defweak)) + if (is_defined (h)) { value = h->u.def.value; value += h->u.def.section->output_section->vma; @@ -4939,8 +4943,7 @@ print_one_symbol (struct bfd_link_hash_entry *hash_entry, void *ptr) { asection *sec = (asection *) ptr; - if ((hash_entry->type == bfd_link_hash_defined - || hash_entry->type == bfd_link_hash_defweak) + if (is_defined (hash_entry) && sec == hash_entry->u.def.section) { print_spaces (SECTION_NAME_MAP_LENGTH); @@ -5062,7 +5065,8 @@ print_input_section (asection *i, bool is_discarded) } print_spaces (SECTION_NAME_MAP_LENGTH - len); - if (i->output_section != NULL + if ((i->flags & SEC_EXCLUDE) == 0 + && i->output_section != NULL && i->output_section->owner == link_info.output_bfd) addr = i->output_section->vma + i->output_offset; else @@ -7233,9 +7237,7 @@ lang_end (void) { h = bfd_link_hash_lookup (link_info.hash, sym->name, false, false, false); - if (h != NULL - && (h->type == bfd_link_hash_defined - || h->type == bfd_link_hash_defweak) + if (is_defined (h) && !bfd_is_const_section (h->u.def.section)) break; } @@ -7254,9 +7256,11 @@ lang_end (void) h = bfd_link_hash_lookup (link_info.hash, entry_symbol.name, false, false, true); - if (h != NULL - && (h->type == bfd_link_hash_defined - || h->type == bfd_link_hash_defweak) + + if (! is_defined (h) || h->u.def.section->output_section == NULL) + h = ldemul_find_alt_start_symbol (&entry_symbol); + + if (is_defined (h) && h->u.def.section->output_section != NULL) { bfd_vma val; @@ -10491,7 +10495,7 @@ setup_section (bfd *ibfd, sec_ptr isection, void *p) /* Allow the BFD backend to copy any private data it understands from the input section to the output section. */ - if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection)) + if (!bfd_copy_private_section_data (ibfd, isection, obfd, osection, NULL)) { err = _("failed to copy private data"); goto loser; @@ -10837,10 +10841,19 @@ cmdline_add_object_only_section (bfd_byte *contents, size_t size) fatal (_("%P: failed to finish output with object-only section\n")); } + /* ibfd needs to be closed *after* obfd, otherwise ld may crash with a + segmentation fault. */ + if (!bfd_close (ibfd)) + einfo (_("%P%F: failed to close input\n")); + /* Must be freed after bfd_close (). */ free (isympp); free (osympp); + /* Must unlink to ensure rename works on Windows. */ + if (unlink (output_filename) && errno != ENOENT) + einfo (_("%P%F: failed to unlink %s\n"), output_filename); + if (rename (ofilename, output_filename)) { unlink (ofilename); @@ -10851,10 +10864,14 @@ cmdline_add_object_only_section (bfd_byte *contents, size_t size) return; loser: - free (isympp); - free (osympp); if (obfd) bfd_close (obfd); + /* ibfd needs to be closed *after* obfd, otherwise ld may crash with a + segmentation fault. */ + if (ibfd) + bfd_close (ibfd); + free (isympp); + free (osympp); if (ofilename) { unlink (ofilename); @@ -10884,6 +10901,9 @@ cmdline_emit_object_only_section (void) lang_init (true); ldexp_init (true); + /* Allow lang_add_section to add new sections. */ + map_head_is_link_order = false; + /* Set up the object-only output. */ lang_final (); |