return this->mode_ == LINKER_SCRIPT && can_continue_name(&c2);
case '*': case '[':
- return this->mode_ == VERSION_SCRIPT;
+ return (this->mode_ == VERSION_SCRIPT
+ || (this->mode_ == LINKER_SCRIPT
+ && can_continue_name(&c2)));
default:
return false;
void
Symbol_assignment::finalize(Symbol_table* symtab, const Layout* layout)
+{
+ this->finalize_maybe_dot(symtab, layout, false, false, 0);
+}
+
+// Finalize a symbol value which can refer to the dot symbol.
+
+void
+Symbol_assignment::finalize_with_dot(Symbol_table* symtab,
+ const Layout* layout,
+ bool dot_has_value,
+ uint64_t dot_value)
+{
+ this->finalize_maybe_dot(symtab, layout, true, dot_has_value, dot_value);
+}
+
+// Finalize a symbol value, internal version.
+
+void
+Symbol_assignment::finalize_maybe_dot(Symbol_table* symtab,
+ const Layout* layout,
+ bool is_dot_available,
+ bool dot_has_value,
+ uint64_t dot_value)
{
// If we were only supposed to provide this symbol, the sym_ field
// will be NULL if the symbol was not referenced.
if (parameters->get_size() == 32)
{
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
- this->sized_finalize<32>(symtab, layout);
+ this->sized_finalize<32>(symtab, layout, is_dot_available, dot_has_value,
+ dot_value);
#else
gold_unreachable();
#endif
else if (parameters->get_size() == 64)
{
#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
- this->sized_finalize<64>(symtab, layout);
+ this->sized_finalize<64>(symtab, layout, is_dot_available, dot_has_value,
+ dot_value);
#else
gold_unreachable();
#endif
template<int size>
void
-Symbol_assignment::sized_finalize(Symbol_table* symtab, const Layout* layout)
-{
+Symbol_assignment::sized_finalize(Symbol_table* symtab, const Layout* layout,
+ bool is_dot_available, bool dot_has_value,
+ uint64_t dot_value)
+{
+ bool dummy;
+ uint64_t final_val = this->val_->eval_maybe_dot(symtab, layout,
+ is_dot_available,
+ dot_has_value, dot_value,
+ &dummy);
Sized_symbol<size>* ssym = symtab->get_sized_symbol<size>(this->sym_);
- ssym->set_value(this->val_->eval(symtab, layout));
+ ssym->set_value(final_val);
+}
+
+// Set the symbol value if the expression yields an absolute value.
+
+void
+Symbol_assignment::set_if_absolute(Symbol_table* symtab, const Layout* layout,
+ bool is_dot_available, bool dot_has_value,
+ uint64_t dot_value)
+{
+ if (this->sym_ == NULL)
+ return;
+
+ bool is_absolute;
+ uint64_t val = this->val_->eval_maybe_dot(symtab, layout, is_dot_available,
+ dot_has_value, dot_value,
+ &is_absolute);
+ if (!is_absolute)
+ return;
+
+ if (parameters->get_size() == 32)
+ {
+#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
+ Sized_symbol<32>* ssym = symtab->get_sized_symbol<32>(this->sym_);
+ ssym->set_value(val);
+#else
+ gold_unreachable();
+#endif
+ }
+ else if (parameters->get_size() == 64)
+ {
+#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
+ Sized_symbol<64>* ssym = symtab->get_sized_symbol<64>(this->sym_);
+ ssym->set_value(val);
+#else
+ gold_unreachable();
+#endif
+ }
+ else
+ gold_unreachable();
}
// Print for debugging.
Expression* value, bool provide,
bool hidden)
{
- if (this->script_sections_.in_sections_clause())
- this->script_sections_.add_symbol_assignment(name, length, value,
- provide, hidden);
+ if (length != 1 || name[0] != '.')
+ {
+ if (this->script_sections_.in_sections_clause())
+ this->script_sections_.add_symbol_assignment(name, length, value,
+ provide, hidden);
+ else
+ {
+ Symbol_assignment* p = new Symbol_assignment(name, length, value,
+ provide, hidden);
+ this->symbol_assignments_.push_back(p);
+ }
+ }
else
{
- Symbol_assignment* p = new Symbol_assignment(name, length, value,
- provide, hidden);
- this->symbol_assignments_.push_back(p);
+ if (provide || hidden)
+ gold_error(_("invalid use of PROVIDE for dot symbol"));
+ if (!this->script_sections_.in_sections_clause())
+ gold_error(_("invalid assignment to dot outside of SECTIONS"));
+ else
+ this->script_sections_.add_dot_assignment(value);
}
}
p != this->symbol_assignments_.end();
++p)
(*p)->add_to_table(symtab);
+ this->script_sections_.add_symbols_to_table(symtab);
}
-// Finalize symbol values.
+// Finalize symbol values. Also check assertions.
void
Script_options::finalize_symbols(Symbol_table* symtab, const Layout* layout)
p != this->symbol_assignments_.end();
++p)
(*p)->finalize(symtab, layout);
+
+ for (Assertions::iterator p = this->assertions_.begin();
+ p != this->assertions_.end();
+ ++p)
+ (*p)->check(symtab, layout);
+
+ this->script_sections_.finalize_symbols(symtab, layout);
+}
+
+// Set section addresses. We set all the symbols which have absolute
+// values. Then we let the SECTIONS clause do its thing. This
+// returns the segment which holds the file header and segment
+// headers, if any.
+
+Output_segment*
+Script_options::set_section_addresses(Symbol_table* symtab, Layout* layout)
+{
+ for (Symbol_assignments::iterator p = this->symbol_assignments_.begin();
+ p != this->symbol_assignments_.end();
+ ++p)
+ (*p)->set_if_absolute(symtab, layout, false, false, 0);
+
+ return this->script_sections_.set_section_addresses(symtab, layout);
}
// This class holds data passed through the parser to the lexer and to
{ "SHORT", SHORT },
{ "SIZEOF", SIZEOF },
{ "SIZEOF_HEADERS", SIZEOF_HEADERS },
+ { "SORT", SORT_BY_NAME },
{ "SORT_BY_ALIGNMENT", SORT_BY_ALIGNMENT },
{ "SORT_BY_NAME", SORT_BY_NAME },
{ "SPECIAL", SPECIAL },
}
}
+// Called by the bison parser to handle SEARCH_DIR. This is handled
+// exactly like a -L option.
+
+extern "C" void
+script_add_search_dir(void* closurev, const char* option, size_t length)
+{
+ Parser_closure* closure = static_cast<Parser_closure*>(closurev);
+ if (closure->command_line() == NULL)
+ gold_warning(_("%s:%d:%d: ignoring SEARCH_DIR; SEARCH_DIR is only valid"
+ " for scripts specified via -T/--script"),
+ closure->filename(), closure->lineno(), closure->charpos());
+ else
+ {
+ std::string s = "-L" + std::string(option, length);
+ script_parse_option(closurev, s.c_str(), s.size());
+ }
+}
+
/* Called by the bison parser to push the lexer into expression
mode. */
script_string_sort_list_add(String_sort_list_ptr pv,
const struct Wildcard_section* string_sort)
{
- pv->push_back(*string_sort);
- return pv;
+ if (pv == NULL)
+ return script_new_string_sort_list(string_sort);
+ else
+ {
+ pv->push_back(*string_sort);
+ return pv;
+ }
}
// Create a new list of strings.