Implement SIZEOF_HEADERS, section constraints, other minor linker
[deliverable/binutils-gdb.git] / gold / script.cc
index 5b49a90d5b4309303f6ad3bedff4c209d8acd402..973c05ce6df9d5c7c351e5da4a24622802689b80 100644 (file)
@@ -393,7 +393,9 @@ Lex::can_start_name(char c, char c2)
       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;
@@ -912,6 +914,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.
@@ -924,7 +949,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 +958,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 +970,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 +1079,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 +1126,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 +1138,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
@@ -1500,6 +1609,7 @@ script_keyword_parsecodes[] =
   { "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 },
@@ -2038,6 +2148,24 @@ script_parse_option(void* closurev, const char* option, size_t length)
     }
 }
 
+// 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.  */
 
@@ -2279,8 +2407,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.
This page took 0.026549 seconds and 4 git commands to generate.