aboutsummaryrefslogtreecommitdiff
path: root/ld/ldlang.c
diff options
context:
space:
mode:
Diffstat (limited to 'ld/ldlang.c')
-rw-r--r--ld/ldlang.c66
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 ();