+ struct bfd_link_hash_entry *h;
+ struct definedness_hash_entry *def;
+
+ memset (&expld.result, 0, sizeof (expld.result));
+
+ switch (tree->type.node_code)
+ {
+ case SIZEOF_HEADERS:
+ link_info.load_phdrs = 1;
+ if (expld.phase != lang_first_phase_enum)
+ {
+ bfd_vma hdr_size = 0;
+ /* Don't find the real header size if only marking sections;
+ The bfd function may cache incorrect data. */
+ if (expld.phase != lang_mark_phase_enum)
+ hdr_size = bfd_sizeof_headers (link_info.output_bfd, &link_info);
+ new_number (hdr_size);
+ }
+ break;
+
+ case DEFINED:
+ h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
+ &link_info,
+ tree->name.name,
+ FALSE, FALSE, TRUE);
+ new_number (h != NULL
+ && (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_defweak
+ || h->type == bfd_link_hash_common)
+ && (!h->ldscript_def
+ || (def = symbol_defined (tree->name.name)) == NULL
+ || def->by_object
+ || def->iteration == (lang_statement_iteration & 255)));
+ break;
+
+ case NAME:
+ if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
+ new_rel_from_abs (expld.dot);
+ else
+ {
+ h = bfd_wrapped_link_hash_lookup (link_info.output_bfd,
+ &link_info,
+ tree->name.name,
+ TRUE, FALSE, TRUE);
+ if (!h)
+ einfo (_("%F%P: bfd_link_hash_lookup failed: %E\n"));
+ else if (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_defweak)
+ {
+ asection *output_section;
+
+ output_section = h->u.def.section->output_section;
+ if (output_section == NULL)
+ {
+ if (expld.phase <= lang_mark_phase_enum)
+ new_rel (h->u.def.value, h->u.def.section);
+ else
+ einfo (_("%X%P:%pS: unresolvable symbol `%s'"
+ " referenced in expression\n"),
+ tree, tree->name.name);
+ }
+ else if (output_section == bfd_abs_section_ptr
+ && (expld.section != bfd_abs_section_ptr
+ || config.sane_expr))
+ new_number (h->u.def.value + h->u.def.section->output_offset);
+ else
+ new_rel (h->u.def.value + h->u.def.section->output_offset,
+ output_section);
+ }
+ else if (expld.phase == lang_final_phase_enum
+ || (expld.phase != lang_mark_phase_enum
+ && expld.assigning_to_dot))
+ einfo (_("%F%P:%pS: undefined symbol `%s'"
+ " referenced in expression\n"),
+ tree, tree->name.name);
+ else if (h->type == bfd_link_hash_new)
+ {
+ h->type = bfd_link_hash_undefined;
+ h->u.undef.abfd = NULL;
+ if (h->u.undef.next == NULL && h != link_info.hash->undefs_tail)
+ bfd_link_add_undef (link_info.hash, h);
+ }
+ if (expld.assign_src == NULL)
+ expld.assign_src = h;
+ else
+ expld.assign_src = (struct bfd_link_hash_entry *) - 1;
+
+ /* Self-assignment is only allowed for absolute symbols
+ defined in a linker script. */
+ if (expld.assign_name != NULL
+ && strcmp (expld.assign_name, tree->name.name) == 0
+ && !(h != NULL
+ && (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_defweak)
+ && h->u.def.section == bfd_abs_section_ptr
+ && (def = symbol_defined (tree->name.name)) != NULL
+ && def->iteration == (lang_statement_iteration & 255)))
+ expld.assign_name = NULL;
+ }
+ break;
+
+ case ADDR:
+ if (expld.phase != lang_first_phase_enum)
+ {
+ lang_output_section_statement_type *os;
+
+ os = lang_output_section_find (tree->name.name);
+ if (os == NULL)
+ {
+ if (expld.phase == lang_final_phase_enum)
+ einfo (_("%F%P:%pS: undefined section `%s'"
+ " referenced in expression\n"),
+ tree, tree->name.name);
+ }
+ else if (os->processed_vma)
+ new_rel (0, os->bfd_section);
+ }
+ break;
+
+ case LOADADDR:
+ if (expld.phase != lang_first_phase_enum)
+ {
+ lang_output_section_statement_type *os;
+
+ os = lang_output_section_find (tree->name.name);
+ if (os == NULL)
+ {
+ if (expld.phase == lang_final_phase_enum)
+ einfo (_("%F%P:%pS: undefined section `%s'"
+ " referenced in expression\n"),
+ tree, tree->name.name);
+ }
+ else if (os->processed_lma)
+ {
+ if (os->load_base == NULL)
+ new_abs (os->bfd_section->lma);
+ else
+ {
+ exp_fold_tree_1 (os->load_base);
+ if (expld.result.valid_p)
+ make_abs ();
+ }
+ }
+ }
+ break;
+
+ case SIZEOF:
+ case ALIGNOF:
+ if (expld.phase != lang_first_phase_enum)
+ {
+ lang_output_section_statement_type *os;
+
+ os = lang_output_section_find (tree->name.name);
+ if (os == NULL)
+ {
+ if (expld.phase == lang_final_phase_enum)
+ einfo (_("%F%P:%pS: undefined section `%s'"
+ " referenced in expression\n"),
+ tree, tree->name.name);
+ new_number (0);
+ }
+ else if (os->bfd_section != NULL)
+ {
+ bfd_vma val;
+
+ if (tree->type.node_code == SIZEOF)
+ val = (os->bfd_section->size
+ / bfd_octets_per_byte (link_info.output_bfd,
+ os->bfd_section));
+ else
+ val = (bfd_vma)1 << os->bfd_section->alignment_power;
+
+ new_number (val);
+ }
+ else
+ new_number (0);
+ }
+ break;
+
+ case LENGTH: