/* Linker command language support.
- Copyright (C) 1991-2014 Free Software Foundation, Inc.
+ Copyright (C) 1991-2015 Free Software Foundation, Inc.
This file is part of the GNU Binutils.
#include "demangle.h"
#include "hashtab.h"
#include "libbfd.h"
+#include "elf-bfd.h"
#ifdef ENABLE_PLUGINS
#include "plugin.h"
#endif /* ENABLE_PLUGINS */
#define obstack_chunk_free free
static const char *entry_symbol_default = "start";
static bfd_boolean placed_commons = FALSE;
-static bfd_boolean stripped_excluded_sections = FALSE;
+static bfd_boolean map_head_is_link_order = FALSE;
static lang_output_section_statement_type *default_common_section;
static bfd_boolean map_option_f;
static bfd_vma print_dot;
static lang_input_statement_type *first_file;
static const char *current_target;
static lang_statement_list_type statement_list;
-static struct bfd_hash_table lang_definedness_table;
static lang_statement_list_type *stat_save[10];
static lang_statement_list_type **stat_save_ptr = &stat_save[0];
static struct unique_sections *unique_section_list;
/* Forward declarations. */
static void exp_init_os (etree_type *);
static lang_input_statement_type *lookup_name (const char *);
-static struct bfd_hash_entry *lang_definedness_newfunc
- (struct bfd_hash_entry *, struct bfd_hash_table *, const char *);
static void insert_undefined (const char *);
static bfd_boolean sort_def_symbol (struct bfd_link_hash_entry *, void *);
static void print_statement (lang_statement_union_type *,
static void lang_do_version_exports_section (void);
static void lang_finalize_version_expr_head
(struct bfd_elf_version_expr_head *);
+static void lang_do_memory_regions (void);
/* Exported variables. */
const char *output_target;
lang_input_file_enum_type file_type,
const char *target)
{
+ if (name != NULL && *name == '=')
+ {
+ lang_input_statement_type *ret;
+ char *sysrooted_name
+ = concat (ld_sysroot, name + 1, (const char *) NULL);
+
+ /* We've now forcibly prepended the sysroot, making the input
+ file independent of the context. Therefore, temporarily
+ force a non-sysrooted context for this statement, so it won't
+ get the sysroot prepended again when opened. (N.B. if it's a
+ script, any child nodes with input files starting with "/"
+ will be handled as "sysrooted" as they'll be found to be
+ within the sysroot subdirectory.) */
+ unsigned int outer_sysrooted = input_flags.sysrooted;
+ input_flags.sysrooted = 0;
+ ret = new_afile (sysrooted_name, file_type, target, TRUE);
+ input_flags.sysrooted = outer_sysrooted;
+ return ret;
+ }
+
return new_afile (name, file_type, target, TRUE);
}
abs_output_section->bfd_section = bfd_abs_section_ptr;
- /* The value "13" is ad-hoc, somewhat related to the expected number of
- assignments in a linker script. */
- if (!bfd_hash_table_init_n (&lang_definedness_table,
- lang_definedness_newfunc,
- sizeof (struct lang_definedness_hash_entry),
- 13))
- einfo (_("%P%F: can not create hash table: %E\n"));
-
asneeded_list_head = NULL;
asneeded_list_tail = &asneeded_list_head;
}
void
lang_finish (void)
{
- bfd_hash_table_free (&lang_definedness_table);
output_section_statement_table_free ();
}
new_region->name_list.name = xstrdup (name);
new_region->name_list.next = NULL;
new_region->next = NULL;
+ new_region->origin_exp = NULL;
new_region->origin = 0;
+ new_region->length_exp = NULL;
new_region->length = ~(bfd_size_type) 0;
new_region->current = 0;
new_region->last_os = NULL;
section->output_section = output->bfd_section;
- if (!link_info.relocatable
- && !stripped_excluded_sections)
+ if (!map_head_is_link_order)
{
asection *s = output->bfd_section->map_tail.s;
output->bfd_section->map_tail.s = section;
|| (bfd_get_format (abfd) == bfd_object
&& ((abfd->flags) & DYNAMIC) != 0
&& s->input_statement.flags.add_DT_NEEDED_for_regular
- && plugin_should_reload (abfd))))
+ && bfd_get_flavour (abfd) == bfd_target_elf_flavour
+ && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0)))
{
s->input_statement.flags.loaded = FALSE;
s->input_statement.flags.reload = TRUE;
einfo ("%F");
}
-/* New-function for the definedness hash table. */
-
-static struct bfd_hash_entry *
-lang_definedness_newfunc (struct bfd_hash_entry *entry,
- struct bfd_hash_table *table ATTRIBUTE_UNUSED,
- const char *name ATTRIBUTE_UNUSED)
-{
- struct lang_definedness_hash_entry *ret
- = (struct lang_definedness_hash_entry *) entry;
-
- if (ret == NULL)
- ret = (struct lang_definedness_hash_entry *)
- bfd_hash_allocate (table, sizeof (struct lang_definedness_hash_entry));
-
- if (ret == NULL)
- einfo (_("%P%F: bfd_hash_allocate failed creating symbol %s\n"), name);
-
- ret->by_object = 0;
- ret->by_script = 0;
- ret->iteration = 0;
- return &ret->root;
-}
-
-/* Called during processing of linker script script expressions.
- For symbols assigned in a linker script, return a struct describing
- where the symbol is defined relative to the current expression,
- otherwise return NULL. */
-
-struct lang_definedness_hash_entry *
-lang_symbol_defined (const char *name)
-{
- return ((struct lang_definedness_hash_entry *)
- bfd_hash_lookup (&lang_definedness_table, name, FALSE, FALSE));
-}
-
-/* Update the definedness state of NAME. */
-
-void
-lang_update_definedness (const char *name, struct bfd_link_hash_entry *h)
-{
- struct lang_definedness_hash_entry *defentry
- = (struct lang_definedness_hash_entry *)
- bfd_hash_lookup (&lang_definedness_table, name, TRUE, FALSE);
-
- if (defentry == NULL)
- einfo (_("%P%F: bfd_hash_lookup failed creating symbol %s\n"), name);
-
- /* If the symbol was already defined, and not by a script, then it
- must be defined by an object file. */
- if (!defentry->by_script
- && h->type != bfd_link_hash_undefined
- && h->type != bfd_link_hash_common
- && h->type != bfd_link_hash_new)
- defentry->by_object = 1;
-
- defentry->by_script = 1;
- defentry->iteration = lang_statement_iteration;
-}
-
/* Add the supplied name to the symbol table as an undefined reference.
This is a two step process as the symbol table doesn't even exist at
the time the ld command line is processed. First we put the name
}
}
- /* TODO: Don't just junk map_head.s, turn them into link_orders. */
- output_section->map_head.link_order = NULL;
- output_section->map_tail.link_order = NULL;
-
if (exclude)
{
/* We don't set bfd_section to NULL since bfd_section of the
link_info.output_bfd->section_count--;
}
}
+}
+
+/* Called from ldwrite to clear out asection.map_head and
+ asection.map_tail for use as link_orders in ldwrite.
+ FIXME: Except for sh64elf.em which starts creating link_orders in
+ its after_allocation routine so needs to call it early. */
+
+void
+lang_clear_os_map (void)
+{
+ lang_output_section_statement_type *os;
+
+ if (map_head_is_link_order)
+ return;
+
+ for (os = &lang_output_section_statement.head->output_section_statement;
+ os != NULL;
+ os = os->next)
+ {
+ asection *output_section;
+
+ if (os->constraint < 0)
+ continue;
+
+ output_section = os->bfd_section;
+ if (output_section == NULL)
+ continue;
+
+ /* TODO: Don't just junk map_head.s, turn them into link_orders. */
+ output_section->map_head.link_order = NULL;
+ output_section->map_tail.link_order = NULL;
+ }
/* Stop future calls to lang_add_section from messing with map_head
and map_tail link_order fields. */
- stripped_excluded_sections = TRUE;
+ map_head_is_link_order = TRUE;
}
static void
osec = output_section->bfd_section;
if (osec == NULL)
osec = bfd_abs_section_ptr;
- exp_fold_tree (tree, osec, &print_dot);
+
+ if (assignment->exp->type.node_class != etree_provide)
+ exp_fold_tree (tree, osec, &print_dot);
+ else
+ expld.result.valid_p = FALSE;
+
if (expld.result.valid_p)
{
bfd_vma value;
}
else
{
- minfo ("*undef* ");
+ if (assignment->exp->type.node_class == etree_provide)
+ minfo ("[!provide]");
+ else
+ minfo ("*undef* ");
#ifdef BFD64
minfo (" ");
#endif
new_stmt = new_stat (lang_output_statement, stat_ptr);
new_stmt->name = output_filename;
-
}
/* Reset the current counters in the regions. */
open_input_bfds (statement_list.head, OPEN_BFD_NORMAL);
#ifdef ENABLE_PLUGINS
- if (plugin_active_plugins_p ())
+ if (link_info.lto_plugin_active)
{
lang_statement_list_type added;
lang_statement_list_type files, inputfiles;
/* PR 13683: We must rerun the assignments prior to running garbage
collection in order to make sure that all symbol aliases are resolved. */
lang_do_assignments (lang_mark_phase_enum);
- expld.phase = lang_first_phase_enum;
- /* Remove unreferenced sections if asked to. */
- lang_gc_sections ();
+ lang_do_memory_regions();
+ expld.phase = lang_first_phase_enum;
/* Size up the common data. */
lang_common ();
+ /* Remove unreferenced sections if asked to. */
+ lang_gc_sections ();
+
/* Update wild statements. */
update_wild_statements (statement_list.head);
lang_new_vers_node (greg, lreg), NULL);
}
+/* Evaluate LENGTH and ORIGIN parts of MEMORY spec */
+
+static void
+lang_do_memory_regions (void)
+{
+ lang_memory_region_type *r = lang_memory_region_list;
+
+ for (; r != NULL; r = r->next)
+ {
+ if (r->origin_exp)
+ {
+ exp_fold_tree_no_dot (r->origin_exp);
+ if (expld.result.valid_p)
+ {
+ r->origin = expld.result.value;
+ r->current = r->origin;
+ }
+ else
+ einfo (_("%F%P: invalid origin for memory region %s\n"), r->name_list.name);
+ }
+ if (r->length_exp)
+ {
+ exp_fold_tree_no_dot (r->length_exp);
+ if (expld.result.valid_p)
+ r->length = expld.result.value;
+ else
+ einfo (_("%F%P: invalid length for memory region %s\n"), r->name_list.name);
+ }
+ }
+}
+
void
lang_add_unique (const char *name)
{