aboutsummaryrefslogtreecommitdiff
path: root/gold/script.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gold/script.cc')
-rw-r--r--gold/script.cc140
1 files changed, 126 insertions, 14 deletions
diff --git a/gold/script.cc b/gold/script.cc
index 5b49a90..734349b 100644
--- a/gold/script.cc
+++ b/gold/script.cc
@@ -913,6 +913,29 @@ Symbol_assignment::add_to_table(Symbol_table* symtab)
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 (this->sym_ == NULL)
@@ -924,7 +947,8 @@ Symbol_assignment::finalize(Symbol_table* symtab, const Layout* layout)
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
@@ -932,7 +956,8 @@ Symbol_assignment::finalize(Symbol_table* symtab, const Layout* layout)
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
@@ -943,10 +968,56 @@ Symbol_assignment::finalize(Symbol_table* symtab, const Layout* layout)
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.
@@ -1006,14 +1077,26 @@ Script_options::add_symbol_assignment(const char* name, size_t length,
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);
}
}
@@ -1041,9 +1124,10 @@ Script_options::add_symbols_to_table(Symbol_table* symtab)
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)
@@ -1052,6 +1136,29 @@ 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
@@ -2279,8 +2386,13 @@ extern "C" String_sort_list_ptr
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.