Report linker script errors with line numbers. Ignore OUTPUT_FORMAT
authorIan Lance Taylor <iant@google.com>
Mon, 7 Jan 2008 05:19:02 +0000 (05:19 +0000)
committerIan Lance Taylor <iant@google.com>
Mon, 7 Jan 2008 05:19:02 +0000 (05:19 +0000)
with three arguments, and ignore OUTPUT_ARCH.

gold/errors.cc
gold/errors.h
gold/options.cc
gold/script.cc
gold/yyscript.y

index c979463dfc25014bcf0138706d7c6682f7e7deac..85c5512c5d919abece0a632a1af60dcc837e5f63 100644 (file)
@@ -44,13 +44,35 @@ Errors::Errors(const char* program_name)
 {
 }
 
-// Initialize the lock_ field.
+// Initialize the lock_ field.  If we have not yet processed the
+// parameters, then we can't initialize, since we don't yet know
+// whether we are using threads.  That is OK, since if we haven't
+// processed the parameters, we haven't created any threads, and we
+// don't need a lock.  Return true if the lock is now initialized.
 
-void
+bool
 Errors::initialize_lock()
 {
-  if (this->lock_ == NULL)
+  if (this->lock_ == NULL && parameters->options_valid())
     this->lock_ = new Lock;
+  return this->lock_ != NULL;
+}
+
+// Increment a counter, holding the lock if available.
+
+void
+Errors::increment_counter(int *counter)
+{
+  if (!this->initialize_lock())
+    {
+      // The lock does not exist, which means that we don't need it.
+      ++*counter;
+    }
+  else
+    {
+      Hold_lock h(*this->lock_);
+      ++*counter;
+    }
 }
 
 // Report a fatal error.
@@ -73,11 +95,7 @@ Errors::error(const char* format, va_list args)
   vfprintf(stderr, format, args);
   fputc('\n', stderr);
 
-  this->initialize_lock();
-  {
-    Hold_lock h(*this->lock_);
-    ++this->error_count_;
-  }
+  this->increment_counter(&this->error_count_);
 }
 
 // Report a warning.
@@ -89,11 +107,7 @@ Errors::warning(const char* format, va_list args)
   vfprintf(stderr, format, args);
   fputc('\n', stderr);
 
-  this->initialize_lock();
-  {
-    Hold_lock h(*this->lock_);
-    ++this->warning_count_;
-  }
+  this->increment_counter(&this->warning_count_);
 }
 
 // Report an error at a reloc location.
@@ -109,11 +123,7 @@ Errors::error_at_location(const Relocate_info<size, big_endian>* relinfo,
   vfprintf(stderr, format, args);
   fputc('\n', stderr);
 
-  this->initialize_lock();
-  {
-    Hold_lock h(*this->lock_);
-    ++this->error_count_;
-  }
+  this->increment_counter(&this->error_count_);
 }
 
 // Report a warning at a reloc location.
@@ -129,11 +139,7 @@ Errors::warning_at_location(const Relocate_info<size, big_endian>* relinfo,
   vfprintf(stderr, format, args);
   fputc('\n', stderr);
 
-  this->initialize_lock();
-  {
-    Hold_lock h(*this->lock_);
-    ++this->warning_count_;
-  }
+  this->increment_counter(&this->warning_count_);
 }
 
 // Issue an undefined symbol error.
@@ -144,7 +150,8 @@ Errors::undefined_symbol(const Symbol* sym,
                         const Relocate_info<size, big_endian>* relinfo,
                         size_t relnum, off_t reloffset)
 {
-  this->initialize_lock();
+  bool initialized = this->initialize_lock();
+  gold_assert(initialized);
   {
     Hold_lock h(*this->lock_);
     if (++this->undefined_symbols_[sym] >= max_undefined_error_report)
index 17b72e10b368b5da6619bb5c19b8ba38e7ba8a13..efc0d1ebe9f1bd9c45ed488e4af39803e95c0d79 100644 (file)
@@ -95,10 +95,14 @@ class Errors
 
   // Initialize the lock.  We don't do this in the constructor because
   // lock initialization wants to know whether we are using threads or
-  // not.
-  void
+  // not.  This returns true if the lock is now initialized.
+  bool
   initialize_lock();
 
+  // Increment a counter, holding the lock.
+  void
+  increment_counter(int*);
+
   // The number of times we report an undefined symbol.
   static const int max_undefined_error_report = 5;
 
index a26139bf425265162eb22b6d8f6c200359daa763..2ba5414a43ce9e4378ae9845bbaf1451bd68e295 100644 (file)
@@ -154,8 +154,7 @@ invoke_script(int argc, char** argv, char* arg, bool long_option,
                                                          arg, long_option,
                                                          &ret);
   if (!read_commandline_script(script_name, cmdline))
-    gold::gold_error(_("%s: unable to parse script file %s\n"),
-                    gold::program_name, arg);
+    gold::gold_error(_("unable to parse script file %s\n"), script_name);
   return ret;
 }
 
index 775aedf6f210c31ceacd8e975bc03fec1090d7de..2b14e3f15bcad88ad92215e09d5b181d513ad607 100644 (file)
@@ -881,7 +881,7 @@ class Parser_closure
   at_eof() const
   { return this->next_token_index_ >= this->tokens_->size(); }
 
-  // Return the next token.
+  // Return the next token, and advance.
   const Token*
   next_token()
   {
@@ -890,6 +890,14 @@ class Parser_closure
     return ret;
   }
 
+  // Return the previous token.
+  const Token*
+  last_token() const
+  {
+    gold_assert(this->next_token_index_ > 0);
+    return &(*this->tokens_)[this->next_token_index_ - 1];
+  }
+
   // Return the list of input files, creating it if necessary.  This
   // is a space leak--we never free the INPUTS_ pointer.
   Input_arguments*
@@ -1240,7 +1248,9 @@ yyerror(void* closurev, const char* message)
 {
   Parser_closure* closure = static_cast<Parser_closure*>(closurev);
 
-  gold_error(_("%s: %s"), closure->filename(), message);
+  const Token* token = closure->last_token();
+  gold_error(_("%s:%d:%d: %s"), closure->filename(), token->lineno(),
+            token->charpos(), message);
 }
 
 // Called by the bison parser to add a file to the link.
index 7cfe7247e782db472236bc622b379f04c4f8f8d1..513241b48578d23026956f36afef7d891ca4340e 100644 (file)
@@ -168,14 +168,24 @@ file_list:
 
 /* A command which may appear at top level of a linker script.  */
 file_cmd:
-         OUTPUT_FORMAT '(' STRING ')'
-       | GROUP
+         GROUP
            { script_start_group(closure); }
          '(' input_list ')'
            { script_end_group(closure); }
         | OPTION '(' STRING ')'
             { script_parse_option(closure, $3); }
        | file_or_sections_cmd
+       | ignore_cmd
+       ;
+
+/* Top level commands which we ignore.  The GNU linker uses these to
+   select the output format, but we don't offer a choice.  Ignoring
+   these is more-or-less OK since most scripts simply explicitly
+   choose the default.  */
+ignore_cmd:
+         OUTPUT_FORMAT '(' STRING ')'
+       | OUTPUT_FORMAT '(' STRING ',' STRING ',' STRING ')'
+       | OUTPUT_ARCH '(' STRING ')'
        ;
 
 /* A list of input file names.  */