Report linker script errors with line numbers. Ignore OUTPUT_FORMAT
with three arguments, and ignore OUTPUT_ARCH.
This commit is contained in:
parent
d4e917ea7f
commit
2dd3e587bd
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Reference in New Issue