diff options
author | Ian Lance Taylor <iant@google.com> | 2008-01-07 05:19:02 +0000 |
---|---|---|
committer | Ian Lance Taylor <iant@google.com> | 2008-01-07 05:19:02 +0000 |
commit | 2dd3e587bdab39d73086c35be60399e096d48b46 (patch) | |
tree | e2b7630d5eceec2576855673cf33948b62a18caf | |
parent | d4e917ea7f50bef2b4f15c1c83aac2a7f58e42e7 (diff) | |
download | gdb-2dd3e587bdab39d73086c35be60399e096d48b46.zip gdb-2dd3e587bdab39d73086c35be60399e096d48b46.tar.gz gdb-2dd3e587bdab39d73086c35be60399e096d48b46.tar.bz2 |
Report linker script errors with line numbers. Ignore OUTPUT_FORMAT
with three arguments, and ignore OUTPUT_ARCH.
-rw-r--r-- | gold/errors.cc | 55 | ||||
-rw-r--r-- | gold/errors.h | 8 | ||||
-rw-r--r-- | gold/options.cc | 3 | ||||
-rw-r--r-- | gold/script.cc | 14 | ||||
-rw-r--r-- | gold/yyscript.y | 14 |
5 files changed, 62 insertions, 32 deletions
diff --git a/gold/errors.cc b/gold/errors.cc index c979463..85c5512 100644 --- a/gold/errors.cc +++ b/gold/errors.cc @@ -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) diff --git a/gold/errors.h b/gold/errors.h index 17b72e1..efc0d1e 100644 --- a/gold/errors.h +++ b/gold/errors.h @@ -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; diff --git a/gold/options.cc b/gold/options.cc index a26139b..2ba5414 100644 --- a/gold/options.cc +++ b/gold/options.cc @@ -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; } diff --git a/gold/script.cc b/gold/script.cc index 775aedf..2b14e3f 100644 --- a/gold/script.cc +++ b/gold/script.cc @@ -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. diff --git a/gold/yyscript.y b/gold/yyscript.y index 7cfe724..513241b 100644 --- a/gold/yyscript.y +++ b/gold/yyscript.y @@ -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. */ |