Home | History | Annotate | Download | only in gold
      1 // errors.cc -- handle errors for gold
      2 
      3 // Copyright (C) 2006-2016 Free Software Foundation, Inc.
      4 // Written by Ian Lance Taylor <iant (at) google.com>.
      5 
      6 // This file is part of gold.
      7 
      8 // This program is free software; you can redistribute it and/or modify
      9 // it under the terms of the GNU General Public License as published by
     10 // the Free Software Foundation; either version 3 of the License, or
     11 // (at your option) any later version.
     12 
     13 // This program is distributed in the hope that it will be useful,
     14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 // GNU General Public License for more details.
     17 
     18 // You should have received a copy of the GNU General Public License
     19 // along with this program; if not, write to the Free Software
     20 // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     21 // MA 02110-1301, USA.
     22 
     23 #include "gold.h"
     24 
     25 #include <cstdarg>
     26 #include <cstdio>
     27 
     28 #include "gold-threads.h"
     29 #include "parameters.h"
     30 #include "object.h"
     31 #include "symtab.h"
     32 #include "errors.h"
     33 
     34 namespace gold
     35 {
     36 
     37 // Class Errors.
     38 
     39 const int Errors::max_undefined_error_report;
     40 
     41 Errors::Errors(const char* program_name)
     42   : program_name_(program_name), lock_(NULL), initialize_lock_(&this->lock_),
     43     error_count_(0), warning_count_(0), undefined_symbols_()
     44 {
     45 }
     46 
     47 // Initialize the lock_ field.  If we have not yet processed the
     48 // parameters, then we can't initialize, since we don't yet know
     49 // whether we are using threads.  That is OK, since if we haven't
     50 // processed the parameters, we haven't created any threads, and we
     51 // don't need a lock.  Return true if the lock is now initialized.
     52 
     53 bool
     54 Errors::initialize_lock()
     55 {
     56   return this->initialize_lock_.initialize();
     57 }
     58 
     59 // Increment a counter, holding the lock if available.
     60 
     61 void
     62 Errors::increment_counter(int *counter)
     63 {
     64   if (!this->initialize_lock())
     65     {
     66       // The lock does not exist, which means that we don't need it.
     67       ++*counter;
     68     }
     69   else
     70     {
     71       Hold_lock h(*this->lock_);
     72       ++*counter;
     73     }
     74 }
     75 
     76 // Report a fatal error.
     77 
     78 void
     79 Errors::fatal(const char* format, va_list args)
     80 {
     81   fprintf(stderr, _("%s: fatal error: "), this->program_name_);
     82   vfprintf(stderr, format, args);
     83   fputc('\n', stderr);
     84   gold_exit(GOLD_ERR);
     85 }
     86 
     87 // Report a fallback error.
     88 
     89 void
     90 Errors::fallback(const char* format, va_list args)
     91 {
     92   fprintf(stderr, _("%s: fatal error: "), this->program_name_);
     93   vfprintf(stderr, format, args);
     94   fputc('\n', stderr);
     95   gold_exit(GOLD_FALLBACK);
     96 }
     97 
     98 // Report an error.
     99 
    100 void
    101 Errors::error(const char* format, va_list args)
    102 {
    103   fprintf(stderr, _("%s: error: "), this->program_name_);
    104   vfprintf(stderr, format, args);
    105   fputc('\n', stderr);
    106 
    107   this->increment_counter(&this->error_count_);
    108 }
    109 
    110 // Report a warning.
    111 
    112 void
    113 Errors::warning(const char* format, va_list args)
    114 {
    115   fprintf(stderr, _("%s: warning: "), this->program_name_);
    116   vfprintf(stderr, format, args);
    117   fputc('\n', stderr);
    118 
    119   this->increment_counter(&this->warning_count_);
    120 }
    121 
    122 // Print an informational message.
    123 
    124 void
    125 Errors::info(const char* format, va_list args)
    126 {
    127   vfprintf(stderr, format, args);
    128   fputc('\n', stderr);
    129 }
    130 
    131 // Report an error at a reloc location.
    132 
    133 template<int size, bool big_endian>
    134 void
    135 Errors::error_at_location(const Relocate_info<size, big_endian>* relinfo,
    136 			  size_t relnum, off_t reloffset,
    137 			  const char* format, va_list args)
    138 {
    139   fprintf(stderr, _("%s: error: "),
    140 	  relinfo->location(relnum, reloffset).c_str());
    141   vfprintf(stderr, format, args);
    142   fputc('\n', stderr);
    143 
    144   this->increment_counter(&this->error_count_);
    145 }
    146 
    147 // Report a warning at a reloc location.
    148 
    149 template<int size, bool big_endian>
    150 void
    151 Errors::warning_at_location(const Relocate_info<size, big_endian>* relinfo,
    152 			    size_t relnum, off_t reloffset,
    153 			    const char* format, va_list args)
    154 {
    155   fprintf(stderr, _("%s: warning: "),
    156 	  relinfo->location(relnum, reloffset).c_str());
    157   vfprintf(stderr, format, args);
    158   fputc('\n', stderr);
    159 
    160   this->increment_counter(&this->warning_count_);
    161 }
    162 
    163 // Issue an undefined symbol error with a caller-supplied location string.
    164 
    165 void
    166 Errors::undefined_symbol(const Symbol* sym, const std::string& location)
    167 {
    168   bool initialized = this->initialize_lock();
    169   gold_assert(initialized);
    170 
    171   const char* zmsg;
    172   {
    173     Hold_lock h(*this->lock_);
    174     if (++this->undefined_symbols_[sym] >= max_undefined_error_report)
    175       return;
    176     if (parameters->options().warn_unresolved_symbols())
    177       {
    178 	++this->warning_count_;
    179 	zmsg = _("warning");
    180       }
    181     else
    182       {
    183 	++this->error_count_;
    184 	zmsg = _("error");
    185       }
    186   }
    187 
    188   const char* const version = sym->version();
    189   if (version == NULL)
    190     fprintf(stderr, _("%s: %s: undefined reference to '%s'\n"),
    191 	    location.c_str(), zmsg, sym->demangled_name().c_str());
    192   else
    193     fprintf(stderr,
    194             _("%s: %s: undefined reference to '%s', version '%s'\n"),
    195 	    location.c_str(), zmsg, sym->demangled_name().c_str(), version);
    196 
    197   if (sym->is_cxx_vtable())
    198     gold_info(_("%s: the vtable symbol may be undefined because "
    199 		"the class is missing its key function"),
    200 	      program_name);
    201   if (sym->is_placeholder())
    202     gold_info(_("%s: the symbol should have been defined by a plugin"),
    203 	      program_name);
    204 }
    205 
    206 // Issue a debugging message.
    207 
    208 void
    209 Errors::debug(const char* format, ...)
    210 {
    211   fprintf(stderr, _("%s: "), this->program_name_);
    212 
    213   va_list args;
    214   va_start(args, format);
    215   vfprintf(stderr, format, args);
    216   va_end(args);
    217 
    218   fputc('\n', stderr);
    219 }
    220 
    221 // The functions which the rest of the code actually calls.
    222 
    223 // Report a fatal error.
    224 
    225 void
    226 gold_fatal(const char* format, ...)
    227 {
    228   va_list args;
    229   va_start(args, format);
    230   parameters->errors()->fatal(format, args);
    231   va_end(args);
    232 }
    233 
    234 // Report a fallback error.
    235 
    236 void
    237 gold_fallback(const char* format, ...)
    238 {
    239   va_list args;
    240   va_start(args, format);
    241   parameters->errors()->fallback(format, args);
    242   va_end(args);
    243 }
    244 
    245 // Report an error.
    246 
    247 void
    248 gold_error(const char* format, ...)
    249 {
    250   va_list args;
    251   va_start(args, format);
    252   parameters->errors()->error(format, args);
    253   va_end(args);
    254 }
    255 
    256 // Report a warning.
    257 
    258 void
    259 gold_warning(const char* format, ...)
    260 {
    261   va_list args;
    262   va_start(args, format);
    263   parameters->errors()->warning(format, args);
    264   va_end(args);
    265 }
    266 
    267 // Print an informational message.
    268 
    269 void
    270 gold_info(const char* format, ...)
    271 {
    272   va_list args;
    273   va_start(args, format);
    274   parameters->errors()->info(format, args);
    275   va_end(args);
    276 }
    277 
    278 // Report an error at a location.
    279 
    280 template<int size, bool big_endian>
    281 void
    282 gold_error_at_location(const Relocate_info<size, big_endian>* relinfo,
    283 		       size_t relnum, off_t reloffset,
    284 		       const char* format, ...)
    285 {
    286   va_list args;
    287   va_start(args, format);
    288   parameters->errors()->error_at_location(relinfo, relnum, reloffset,
    289 					  format, args);
    290   va_end(args);
    291 }
    292 
    293 // Report a warning at a location.
    294 
    295 template<int size, bool big_endian>
    296 void
    297 gold_warning_at_location(const Relocate_info<size, big_endian>* relinfo,
    298 			 size_t relnum, off_t reloffset,
    299 			 const char* format, ...)
    300 {
    301   va_list args;
    302   va_start(args, format);
    303   parameters->errors()->warning_at_location(relinfo, relnum, reloffset,
    304 					    format, args);
    305   va_end(args);
    306 }
    307 
    308 // Report an undefined symbol.
    309 
    310 void
    311 gold_undefined_symbol(const Symbol* sym)
    312 {
    313   parameters->errors()->undefined_symbol(sym, sym->object()->name().c_str());
    314 }
    315 
    316 // Report an undefined symbol at a reloc location
    317 
    318 template<int size, bool big_endian>
    319 void
    320 gold_undefined_symbol_at_location(const Symbol* sym,
    321 		      const Relocate_info<size, big_endian>* relinfo,
    322 		      size_t relnum, off_t reloffset)
    323 {
    324   parameters->errors()->undefined_symbol(sym,
    325                                          relinfo->location(relnum, reloffset));
    326 }
    327 
    328 #ifdef HAVE_TARGET_32_LITTLE
    329 template
    330 void
    331 gold_error_at_location<32, false>(const Relocate_info<32, false>* relinfo,
    332 				  size_t relnum, off_t reloffset,
    333 				  const char* format, ...);
    334 #endif
    335 
    336 #ifdef HAVE_TARGET_32_BIG
    337 template
    338 void
    339 gold_error_at_location<32, true>(const Relocate_info<32, true>* relinfo,
    340 				 size_t relnum, off_t reloffset,
    341 				 const char* format, ...);
    342 #endif
    343 
    344 #ifdef HAVE_TARGET_64_LITTLE
    345 template
    346 void
    347 gold_error_at_location<64, false>(const Relocate_info<64, false>* relinfo,
    348 				  size_t relnum, off_t reloffset,
    349 				  const char* format, ...);
    350 #endif
    351 
    352 #ifdef HAVE_TARGET_64_BIG
    353 template
    354 void
    355 gold_error_at_location<64, true>(const Relocate_info<64, true>* relinfo,
    356 				 size_t relnum, off_t reloffset,
    357 				 const char* format, ...);
    358 #endif
    359 
    360 #ifdef HAVE_TARGET_32_LITTLE
    361 template
    362 void
    363 gold_warning_at_location<32, false>(const Relocate_info<32, false>* relinfo,
    364 				    size_t relnum, off_t reloffset,
    365 				    const char* format, ...);
    366 #endif
    367 
    368 #ifdef HAVE_TARGET_32_BIG
    369 template
    370 void
    371 gold_warning_at_location<32, true>(const Relocate_info<32, true>* relinfo,
    372 				   size_t relnum, off_t reloffset,
    373 				   const char* format, ...);
    374 #endif
    375 
    376 #ifdef HAVE_TARGET_64_LITTLE
    377 template
    378 void
    379 gold_warning_at_location<64, false>(const Relocate_info<64, false>* relinfo,
    380 				    size_t relnum, off_t reloffset,
    381 				    const char* format, ...);
    382 #endif
    383 
    384 #ifdef HAVE_TARGET_64_BIG
    385 template
    386 void
    387 gold_warning_at_location<64, true>(const Relocate_info<64, true>* relinfo,
    388 				   size_t relnum, off_t reloffset,
    389 				   const char* format, ...);
    390 #endif
    391 
    392 #ifdef HAVE_TARGET_32_LITTLE
    393 template
    394 void
    395 gold_undefined_symbol_at_location<32, false>(
    396     const Symbol* sym,
    397     const Relocate_info<32, false>* relinfo,
    398     size_t relnum, off_t reloffset);
    399 #endif
    400 
    401 #ifdef HAVE_TARGET_32_BIG
    402 template
    403 void
    404 gold_undefined_symbol_at_location<32, true>(
    405     const Symbol* sym,
    406     const Relocate_info<32, true>* relinfo,
    407     size_t relnum, off_t reloffset);
    408 #endif
    409 
    410 #ifdef HAVE_TARGET_64_LITTLE
    411 template
    412 void
    413 gold_undefined_symbol_at_location<64, false>(
    414     const Symbol* sym,
    415     const Relocate_info<64, false>* relinfo,
    416     size_t relnum, off_t reloffset);
    417 #endif
    418 
    419 #ifdef HAVE_TARGET_64_BIG
    420 template
    421 void
    422 gold_undefined_symbol_at_location<64, true>(
    423     const Symbol* sym,
    424     const Relocate_info<64, true>* relinfo,
    425     size_t relnum, off_t reloffset);
    426 #endif
    427 
    428 } // End namespace gold.
    429