* nto-procfs.c (get_regset): Pass correct pointer.
[deliverable/binutils-gdb.git] / gold / script.cc
index 442c4127764c1b0215b841e87ead1d97791dfa32..86ce13bf7fe89777d3784511e58a780a5a70bb22 100644 (file)
 #include "parameters.h"
 #include "layout.h"
 #include "symtab.h"
+#include "target-select.h"
 #include "script.h"
 #include "script-c.h"
+#include "incremental.h"
 
 namespace gold
 {
@@ -1162,9 +1164,12 @@ class Parser_closure
                 bool in_group, bool is_in_sysroot,
                  Command_line* command_line,
                 Script_options* script_options,
-                Lex* lex)
+                Lex* lex,
+                bool skip_on_incompatible_target)
     : filename_(filename), posdep_options_(posdep_options),
       in_group_(in_group), is_in_sysroot_(is_in_sysroot),
+      skip_on_incompatible_target_(skip_on_incompatible_target),
+      found_incompatible_target_(false),
       command_line_(command_line), script_options_(script_options),
       version_script_info_(script_options->version_script_info()),
       lex_(lex), lineno_(0), charpos_(0), lex_mode_stack_(), inputs_(NULL)
@@ -1196,6 +1201,30 @@ class Parser_closure
   is_in_sysroot() const
   { return this->is_in_sysroot_; }
 
+  // Whether to skip to the next file with the same name if we find an
+  // incompatible target in an OUTPUT_FORMAT statement.
+  bool
+  skip_on_incompatible_target() const
+  { return this->skip_on_incompatible_target_; }
+
+  // Stop skipping to the next flie on an incompatible target.  This
+  // is called when we make some unrevocable change to the data
+  // structures.
+  void
+  clear_skip_on_incompatible_target()
+  { this->skip_on_incompatible_target_ = false; }
+
+  // Whether we found an incompatible target in an OUTPUT_FORMAT
+  // statement.
+  bool
+  found_incompatible_target() const
+  { return this->found_incompatible_target_; }
+
+  // Note that we found an incompatible target.
+  void
+  set_found_incompatible_target()
+  { this->found_incompatible_target_ = true; }
+
   // Returns the Command_line structure passed in at constructor time.
   // This value may be NULL.  The caller may modify this, which modifies
   // the passed-in Command_line object (not a copy).
@@ -1296,6 +1325,12 @@ class Parser_closure
   bool in_group_;
   // Whether the script was found in a sysrooted directory.
   bool is_in_sysroot_;
+  // If this is true, then if we find an OUTPUT_FORMAT with an
+  // incompatible target, then we tell the parser to abort so that we
+  // can search for the next file with the same name.
+  bool skip_on_incompatible_target_;
+  // True if we found an OUTPUT_FORMAT with an incompatible target.
+  bool found_incompatible_target_;
   // May be NULL if the user chooses not to pass one in.
   Command_line* command_line_;
   // Options which may be set from any linker script.
@@ -1321,10 +1356,10 @@ class Parser_closure
 // as a script.  Return true if the file was handled.
 
 bool
-read_input_script(Workqueue* workqueue, const General_options& options,
-                 Symbol_table* symtab, Layout* layout,
-                 Dirsearch* dirsearch, Input_objects* input_objects,
-                 Mapfile* mapfile, Input_group* input_group,
+read_input_script(Workqueue* workqueue, Symbol_table* symtab, Layout* layout,
+                 Dirsearch* dirsearch, int dirindex,
+                 Input_objects* input_objects, Mapfile* mapfile,
+                 Input_group* input_group,
                  const Input_argument* input_argument,
                  Input_file* input_file, Task_token* next_blocker,
                  bool* used_next_blocker)
@@ -1342,10 +1377,21 @@ read_input_script(Workqueue* workqueue, const General_options& options,
                         input_file->is_in_sysroot(),
                          NULL,
                         layout->script_options(),
-                        &lex);
+                        &lex,
+                        input_file->will_search_for());
 
   if (yyparse(&closure) != 0)
-    return false;
+    {
+      if (closure.found_incompatible_target())
+       {
+         Read_symbols::incompatible_warning(input_argument, input_file);
+         Read_symbols::requeue(workqueue, input_objects, symtab, layout,
+                               dirsearch, dirindex, mapfile, input_argument,
+                               input_group, next_blocker);
+         return true;
+       }
+      return false;
+    }
 
   if (!closure.saw_inputs())
     return true;
@@ -1363,12 +1409,19 @@ read_input_script(Workqueue* workqueue, const General_options& options,
          nb = new Task_token(true);
          nb->add_blocker();
        }
-      workqueue->queue_soon(new Read_symbols(options, input_objects, symtab,
-                                            layout, dirsearch, mapfile, &*p,
+      workqueue->queue_soon(new Read_symbols(input_objects, symtab,
+                                            layout, dirsearch, 0, mapfile, &*p,
                                             input_group, this_blocker, nb));
       this_blocker = nb;
     }
 
+  if (layout->incremental_inputs())
+    {
+      // Like new Read_symbols(...) above, we rely on close.inputs()
+      // getting leaked by closure.
+      Script_info* info = new Script_info(closure.inputs());
+      layout->incremental_inputs()->report_script(input_argument, info);
+    }
   *used_next_blocker = true;
 
   return true;
@@ -1398,7 +1451,8 @@ read_script_file(const char* filename, Command_line* cmdline,
     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))
+  int dummy = 0;
+  if (!input_file.open(dirsearch, task, &dummy))
     return false;
 
   std::string input_string;
@@ -1413,7 +1467,8 @@ read_script_file(const char* filename, Command_line* cmdline,
                         input_file.is_in_sysroot(),
                          cmdline,
                         script_options,
-                        &lex);
+                        &lex,
+                        false);
   if (yyparse(&closure) != 0)
     {
       input_file.file().unlock(task);
@@ -1472,7 +1527,7 @@ Script_options::define_symbol(const char* definition)
   Position_dependent_options posdep_options;
 
   Parser_closure closure("command line", posdep_options, false, false, NULL,
-                        this, &lex);
+                        this, &lex, false);
 
   if (yyparse(&closure) != 0)
     return false;
@@ -2072,6 +2127,19 @@ yyerror(void* closurev, const char* message)
             closure->charpos(), message);
 }
 
+// Called by the bison parser to add an external symbol to the link.
+
+extern "C" void
+script_add_extern(void* closurev, const char* name, size_t length)
+{
+  // We treat exactly like -u NAME.  FIXME: If it seems useful, we
+  // could handle this after the command line has been read, by adding
+  // entries to the symbol table directly.
+  std::string arg("--undefined=");
+  arg.append(name, length);
+  script_parse_option(closurev, arg.c_str(), arg.size());
+}
+
 // Called by the bison parser to add a file to the link.
 
 extern "C" void
@@ -2192,6 +2260,7 @@ script_set_symbol(void* closurev, const char* name, size_t length,
   const bool hidden = hiddeni != 0;
   closure->script_options()->add_symbol_assignment(name, length, value,
                                                   provide, hidden);
+  closure->clear_skip_on_incompatible_target();
 }
 
 // Called by the bison parser to add an assertion.
@@ -2202,6 +2271,7 @@ script_add_assertion(void* closurev, Expression* check, const char* message,
 {
   Parser_closure* closure = static_cast<Parser_closure*>(closurev);
   closure->script_options()->add_assertion(check, message, messagelen);
+  closure->clear_skip_on_incompatible_target();
 }
 
 // Called by the bison parser to parse an OPTION.
@@ -2231,6 +2301,34 @@ script_parse_option(void* closurev, const char* option, size_t length)
       // 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. :(
     }
+  closure->clear_skip_on_incompatible_target();
+}
+
+// Called by the bison parser to handle OUTPUT_FORMAT.  OUTPUT_FORMAT
+// takes either one or three arguments.  In the three argument case,
+// the format depends on the endianness option, which we don't
+// currently support (FIXME).  If we see an OUTPUT_FORMAT for the
+// wrong format, then we want to search for a new file.  Returning 0
+// here will cause the parser to immediately abort.
+
+extern "C" int
+script_check_output_format(void* closurev,
+                          const char* default_name, size_t default_length,
+                          const char*, size_t, const char*, size_t)
+{
+  Parser_closure* closure = static_cast<Parser_closure*>(closurev);
+  std::string name(default_name, default_length);
+  Target* target = select_target_by_name(name.c_str());
+  if (target == NULL || !parameters->is_compatible_target(target))
+    {
+      if (closure->skip_on_incompatible_target())
+       {
+         closure->set_found_incompatible_target();
+         return 0;
+       }
+      // FIXME: Should we warn about the unknown target?
+    }
+  return 1;
 }
 
 // Called by the bison parser to handle SEARCH_DIR.  This is handled
@@ -2389,6 +2487,7 @@ script_start_sections(void* closurev)
 {
   Parser_closure* closure = static_cast<Parser_closure*>(closurev);
   closure->script_options()->script_sections()->start_sections();
+  closure->clear_skip_on_incompatible_target();
 }
 
 // Called by the bison parser to finish a SECTIONS clause.
@@ -2581,6 +2680,7 @@ script_add_phdr(void* closurev, const char* name, size_t namelen,
   Script_sections* ss = closure->script_options()->script_sections();
   ss->add_phdr(name, namelen, type, includes_filehdr, includes_phdrs,
               is_flags_valid, info->flags, info->load_address);
+  closure->clear_skip_on_incompatible_target();
 }
 
 // Convert a program header string to a type.
This page took 0.027009 seconds and 4 git commands to generate.