* options.h (class General_options): Add --fatal-warnings.
[deliverable/binutils-gdb.git] / gold / script.cc
index 7cf3c7e6e104dcc121c9003f8079e310931bd756..a808b2e31d1c4d734d89a70e77c8b67d1077628b 100644 (file)
 
 #include "gold.h"
 
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
 #include <fnmatch.h>
 #include <string>
 #include <vector>
-#include <cstdio>
-#include <cstdlib>
 #include "filenames.h"
 
 #include "elfcpp.h"
@@ -846,47 +847,6 @@ Lex::next_token()
   return &this->token_;
 }
 
-// A trivial task which waits for THIS_BLOCKER to be clear and then
-// clears NEXT_BLOCKER.  THIS_BLOCKER may be NULL.
-
-class Script_unblock : public Task
-{
- public:
-  Script_unblock(Task_token* this_blocker, Task_token* next_blocker)
-    : this_blocker_(this_blocker), next_blocker_(next_blocker)
-  { }
-
-  ~Script_unblock()
-  {
-    if (this->this_blocker_ != NULL)
-      delete this->this_blocker_;
-  }
-
-  Task_token*
-  is_runnable()
-  {
-    if (this->this_blocker_ != NULL && this->this_blocker_->is_blocked())
-      return this->this_blocker_;
-    return NULL;
-  }
-
-  void
-  locks(Task_locker* tl)
-  { tl->add(this, this->next_blocker_); }
-
-  void
-  run(Workqueue*)
-  { }
-
-  std::string
-  get_name() const
-  { return "Script_unblock"; }
-
- private:
-  Task_token* this_blocker_;
-  Task_token* next_blocker_;
-};
-
 // class Symbol_assignment.
 
 // Add the symbol to the symbol table.  This makes sure the symbol is
@@ -895,6 +855,10 @@ class Script_unblock : public Task
 // necessarily evaluate the expression until all ordinary symbols have
 // been finalized.
 
+// The GNU linker lets symbol assignments in the linker script
+// silently override defined symbols in object files.  We are
+// compatible.  FIXME: Should we issue a warning?
+
 void
 Symbol_assignment::add_to_table(Symbol_table* symtab)
 {
@@ -907,7 +871,8 @@ Symbol_assignment::add_to_table(Symbol_table* symtab)
                                          elfcpp::STB_GLOBAL,
                                          vis,
                                          0, // nonvis
-                                         this->provide_);
+                                         this->provide_,
+                                          true); // force_override
 }
 
 // Finalize a symbol value.
@@ -915,7 +880,7 @@ 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);
+  this->finalize_maybe_dot(symtab, layout, false, 0, NULL);
 }
 
 // Finalize a symbol value which can refer to the dot symbol.
@@ -923,10 +888,10 @@ Symbol_assignment::finalize(Symbol_table* symtab, const Layout* layout)
 void
 Symbol_assignment::finalize_with_dot(Symbol_table* symtab,
                                     const Layout* layout,
-                                    bool dot_has_value,
-                                    uint64_t dot_value)
+                                    uint64_t dot_value,
+                                    Output_section* dot_section)
 {
-  this->finalize_maybe_dot(symtab, layout, true, dot_has_value, dot_value);
+  this->finalize_maybe_dot(symtab, layout, true, dot_value, dot_section);
 }
 
 // Finalize a symbol value, internal version.
@@ -935,8 +900,8 @@ void
 Symbol_assignment::finalize_maybe_dot(Symbol_table* symtab,
                                      const Layout* layout,
                                      bool is_dot_available,
-                                     bool dot_has_value,
-                                     uint64_t dot_value)
+                                     uint64_t dot_value,
+                                     Output_section* dot_section)
 {
   // If we were only supposed to provide this symbol, the sym_ field
   // will be NULL if the symbol was not referenced.
@@ -946,20 +911,20 @@ Symbol_assignment::finalize_maybe_dot(Symbol_table* symtab,
       return;
     }
 
-  if (parameters->get_size() == 32)
+  if (parameters->target().get_size() == 32)
     {
 #if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
-      this->sized_finalize<32>(symtab, layout, is_dot_available, dot_has_value,
-                              dot_value);
+      this->sized_finalize<32>(symtab, layout, is_dot_available, dot_value,
+                              dot_section);
 #else
       gold_unreachable();
 #endif
     }
-  else if (parameters->get_size() == 64)
+  else if (parameters->target().get_size() == 64)
     {
 #if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
-      this->sized_finalize<64>(symtab, layout, is_dot_available, dot_has_value,
-                              dot_value);
+      this->sized_finalize<64>(symtab, layout, is_dot_available, dot_value,
+                              dot_section);
 #else
       gold_unreachable();
 #endif
@@ -971,36 +936,37 @@ Symbol_assignment::finalize_maybe_dot(Symbol_table* symtab,
 template<int size>
 void
 Symbol_assignment::sized_finalize(Symbol_table* symtab, const Layout* layout,
-                                 bool is_dot_available, bool dot_has_value,
-                                 uint64_t dot_value)
+                                 bool is_dot_available, uint64_t dot_value,
+                                 Output_section* dot_section)
 {
-  bool dummy;
-  uint64_t final_val = this->val_->eval_maybe_dot(symtab, layout,
+  Output_section* section;
+  uint64_t final_val = this->val_->eval_maybe_dot(symtab, layout, true,
                                                  is_dot_available,
-                                                 dot_has_value, dot_value,
-                                                 &dummy);
+                                                 dot_value, dot_section,
+                                                 &section);
   Sized_symbol<size>* ssym = symtab->get_sized_symbol<size>(this->sym_);
   ssym->set_value(final_val);
+  if (section != NULL)
+    ssym->set_output_section(section);
 }
 
 // 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)
+                                  bool is_dot_available, 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)
+  Output_section* val_section;
+  uint64_t val = this->val_->eval_maybe_dot(symtab, layout, false,
+                                           is_dot_available, dot_value,
+                                           NULL, &val_section);
+  if (val_section != NULL)
     return;
 
-  if (parameters->get_size() == 32)
+  if (parameters->target().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_);
@@ -1009,7 +975,7 @@ Symbol_assignment::set_if_absolute(Symbol_table* symtab, const Layout* layout,
       gold_unreachable();
 #endif
     }
-  else if (parameters->get_size() == 64)
+  else if (parameters->target().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_);
@@ -1050,7 +1016,7 @@ Symbol_assignment::print(FILE* f) const
 void
 Script_assertion::check(const Symbol_table* symtab, const Layout* layout)
 {
-  if (!this->check_->eval(symtab, layout))
+  if (!this->check_->eval(symtab, layout, true))
     gold_error("%s", this->message_.c_str());
 }
 
@@ -1117,6 +1083,15 @@ Script_options::add_assertion(Expression* check, const char* message,
     }
 }
 
+// Create sections required by any linker scripts.
+
+void
+Script_options::create_script_sections(Layout* layout)
+{
+  if (this->saw_sections_clause())
+    this->script_sections_.create_sections(layout);
+}
+
 // Add any symbols we are defining to the symbol table.
 
 void
@@ -1158,7 +1133,7 @@ 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);
+    (*p)->set_if_absolute(symtab, layout, false, 0);
 
   return this->script_sections_.set_section_addresses(symtab, layout);
 }
@@ -1332,8 +1307,7 @@ class Parser_closure
 };
 
 // FILE was found as an argument on the command line.  Try to read it
-// as a script.  We've already read BYTES of data into P, but we
-// ignore that.  Return true if the file was handled.
+// as a script.  Return true if the file was handled.
 
 bool
 read_input_script(Workqueue* workqueue, const General_options& options,
@@ -1341,9 +1315,11 @@ read_input_script(Workqueue* workqueue, const General_options& options,
                  Dirsearch* dirsearch, Input_objects* input_objects,
                  Input_group* input_group,
                  const Input_argument* input_argument,
-                 Input_file* input_file, const unsigned char*, off_t,
-                 Task_token* this_blocker, Task_token* next_blocker)
+                 Input_file* input_file, Task_token* next_blocker,
+                 bool* used_next_blocker)
 {
+  *used_next_blocker = false;
+
   std::string input_string;
   Lex::read_file(input_file, &input_string);
 
@@ -1360,20 +1336,10 @@ read_input_script(Workqueue* workqueue, const General_options& options,
   if (yyparse(&closure) != 0)
     return false;
 
-  // THIS_BLOCKER must be clear before we may add anything to the
-  // symbol table.  We are responsible for unblocking NEXT_BLOCKER
-  // when we are done.  We are responsible for deleting THIS_BLOCKER
-  // when it is unblocked.
-
   if (!closure.saw_inputs())
-    {
-      // The script did not add any files to read.  Note that we are
-      // not permitted to call NEXT_BLOCKER->unblock() here even if
-      // THIS_BLOCKER is NULL, as we do not hold the workqueue lock.
-      workqueue->queue(new Script_unblock(this_blocker, next_blocker));
-      return true;
-    }
+    return true;
 
+  Task_token* this_blocker = NULL;
   for (Input_arguments::const_iterator p = closure.inputs()->begin();
        p != closure.inputs()->end();
        ++p)
@@ -1386,12 +1352,14 @@ read_input_script(Workqueue* workqueue, const General_options& options,
          nb = new Task_token(true);
          nb->add_blocker();
        }
-      workqueue->queue(new Read_symbols(options, input_objects, symtab,
-                                       layout, dirsearch, &*p,
-                                       input_group, this_blocker, nb));
+      workqueue->queue_soon(new Read_symbols(options, input_objects, symtab,
+                                            layout, dirsearch, &*p,
+                                            input_group, this_blocker, nb));
       this_blocker = nb;
     }
 
+  *used_next_blocker = true;
+
   return true;
 }
 
@@ -1412,8 +1380,11 @@ read_script_file(const char* filename, Command_line* cmdline,
   // so we invent a fake value.
   const Task* task = reinterpret_cast<const Task*>(-1);
 
-  Input_file_argument input_argument(filename, false, "", false,
-                                    cmdline->position_dependent_options());
+  // We don't want this file to be opened in binary mode.
+  Position_dependent_options posdep = cmdline->position_dependent_options();
+  if (posdep.format_enum() == General_options::OBJECT_FORMAT_BINARY)
+    posdep.set_format_enum(General_options::OBJECT_FORMAT_ELF);
+  Input_file_argument input_argument(filename, false, "", false, posdep);
   Input_file input_file(&input_argument);
   if (!input_file.open(cmdline->options(), dirsearch, task))
     return false;
@@ -1429,7 +1400,7 @@ read_script_file(const char* filename, Command_line* cmdline,
                         false,
                         input_file.is_in_sysroot(),
                          cmdline,
-                        cmdline->script_options(),
+                        &cmdline->script_options(),
                         &lex);
   if (yyparse(&closure) != 0)
     {
@@ -1738,13 +1709,22 @@ struct Version_tree {
 };
 
 Version_script_info::~Version_script_info()
+{
+  this->clear();
+}
+
+void
+Version_script_info::clear()
 {
   for (size_t k = 0; k < dependency_lists_.size(); ++k)
     delete dependency_lists_[k];
+  this->dependency_lists_.clear();
   for (size_t k = 0; k < version_trees_.size(); ++k)
     delete version_trees_[k];
+  this->version_trees_.clear();
   for (size_t k = 0; k < expression_lists_.size(); ++k)
     delete expression_lists_[k];
+  this->expression_lists_.clear();
 }
 
 std::vector<std::string>
@@ -2019,7 +1999,7 @@ script_add_file(void* closurev, const char* name, size_t length)
     {
       if (closure->is_in_sysroot())
        {
-         const std::string& sysroot(parameters->sysroot());
+         const std::string& sysroot(parameters->options().sysroot());
          gold_assert(!sysroot.empty());
          name_string = sysroot + name_string;
        }
@@ -2077,7 +2057,7 @@ extern "C" void
 script_start_as_needed(void* closurev)
 {
   Parser_closure* closure = static_cast<Parser_closure*>(closurev);
-  closure->position_dependent_options().set_as_needed();
+  closure->position_dependent_options().set_as_needed(true);
 }
 
 // Called by the bison parser at the end of an AS_NEEDED list.
@@ -2086,7 +2066,7 @@ extern "C" void
 script_end_as_needed(void* closurev)
 {
   Parser_closure* closure = static_cast<Parser_closure*>(closurev);
-  closure->position_dependent_options().clear_as_needed();
+  closure->position_dependent_options().set_as_needed(false);
 }
 
 // Called by the bison parser to set the entry symbol.
@@ -2094,8 +2074,20 @@ script_end_as_needed(void* closurev)
 extern "C" void
 script_set_entry(void* closurev, const char* entry, size_t length)
 {
-  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
-  closure->script_options()->set_entry(entry, length);
+  // We'll parse this exactly the same as --entry=ENTRY on the commandline
+  // TODO(csilvers): FIXME -- call set_entry directly.
+  std::string arg("--entry=");
+  arg.append(entry, length);
+  script_parse_option(closurev, arg.c_str(), arg.size());
+}
+
+// Called by the bison parser to set whether to define common symbols.
+
+extern "C" void
+script_set_common_allocation(void* closurev, int set)
+{
+  const char* arg = set != 0 ? "--define-common" : "--no-define-common";
+  script_parse_option(closurev, arg, strlen(arg));
 }
 
 // Called by the bison parser to define a symbol.
@@ -2140,11 +2132,13 @@ script_parse_option(void* closurev, const char* option, size_t length)
   else
     {
       bool past_a_double_dash_option = false;
-      char* mutable_option = strndup(option, length);
+      const char* mutable_option = strndup(option, length);
       gold_assert(mutable_option != NULL);
       closure->command_line()->process_one_option(1, &mutable_option, 0,
                                                   &past_a_double_dash_option);
-      free(mutable_option);
+      // The General_options class will quite possibly store a pointer
+      // into mutable_option, so we can't free it.  In cases the class
+      // does not store such a pointer, this is a memory leak.  Alas. :(
     }
 }
 
This page took 0.048216 seconds and 4 git commands to generate.