+/* New-function for the definedness hash table. */
+
+static struct bfd_hash_entry *
+definedness_newfunc (struct bfd_hash_entry *entry,
+ struct bfd_hash_table *table ATTRIBUTE_UNUSED,
+ const char *name ATTRIBUTE_UNUSED)
+{
+ struct definedness_hash_entry *ret = (struct definedness_hash_entry *) entry;
+
+ if (ret == NULL)
+ ret = (struct definedness_hash_entry *)
+ bfd_hash_allocate (table, sizeof (struct definedness_hash_entry));
+
+ if (ret == NULL)
+ einfo (_("%F%P: bfd_hash_allocate failed creating symbol %s\n"), name);
+
+ ret->by_object = 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. */
+
+static struct definedness_hash_entry *
+symbol_defined (const char *name)
+{
+ return ((struct definedness_hash_entry *)
+ bfd_hash_lookup (&definedness_table, name, FALSE, FALSE));
+}
+
+/* Update the definedness state of NAME. Return FALSE if script symbol
+ is multiply defining a strong symbol in an object. */
+
+static bfd_boolean
+update_definedness (const char *name, struct bfd_link_hash_entry *h)
+{
+ bfd_boolean ret;
+ struct definedness_hash_entry *defentry
+ = (struct definedness_hash_entry *)
+ bfd_hash_lookup (&definedness_table, name, TRUE, FALSE);
+
+ if (defentry == NULL)
+ einfo (_("%F%P: 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 or by the linker target code. */
+ ret = TRUE;
+ if (!h->ldscript_def
+ && (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_defweak
+ || h->type == bfd_link_hash_common))
+ {
+ defentry->by_object = 1;
+ if (h->type == bfd_link_hash_defined
+ && h->u.def.section->output_section != NULL
+ && !h->linker_def)
+ ret = FALSE;
+ }
+
+ defentry->iteration = lang_statement_iteration;
+ defentry->final_sec = bfd_abs_section_ptr;
+ if (expld.phase == lang_final_phase_enum
+ && expld.rel_from_abs
+ && expld.result.section == bfd_abs_section_ptr)
+ defentry->final_sec = section_for_dot ();
+ return ret;
+}
+
+static void
+fold_segment_end (seg_align_type *seg)
+{
+ if (expld.phase == lang_first_phase_enum
+ || expld.section != bfd_abs_section_ptr)
+ {
+ expld.result.valid_p = FALSE;
+ }
+ else if (seg->phase == exp_seg_align_seen
+ || seg->phase == exp_seg_relro_seen)
+ {
+ seg->phase = exp_seg_end_seen;
+ seg->end = expld.result.value;
+ }
+ else if (seg->phase == exp_seg_done
+ || seg->phase == exp_seg_adjust
+ || seg->phase == exp_seg_relro_adjust)
+ {
+ /* OK. */
+ }
+ else
+ expld.result.valid_p = FALSE;
+}
+