Home | History | Annotate | Download | only in gold
      1 // errors.cc -- handle errors for gold
      2 
      3 // Copyright (C) 2006-2014 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                 " (see go/missingkeymethod)"),
    201 	      program_name);
    202 }
    203 
    204 // Issue a debugging message.
    205 
    206 void
    207 Errors::debug(const char* format, ...)
    208 {
    209   fprintf(stderr, _("%s: "), this->program_name_);
    210 
    211   va_list args;
    212   va_start(args, format);
    213   vfprintf(stderr, format, args);
    214   va_end(args);
    215 
    216   fputc('\n', stderr);
    217 }
    218 
    219 // The functions which the rest of the code actually calls.
    220 
    221 // Report a fatal error.
    222 
    223 void
    224 gold_fatal(const char* format, ...)
    225 {
    226   va_list args;
    227   va_start(args, format);
    228   parameters->errors()->fatal(format, args);
    229   va_end(args);
    230 }
    231 
    232 // Report a fallback error.
    233 
    234 void
    235 gold_fallback(const char* format, ...)
    236 {
    237   va_list args;
    238   va_start(args, format);
    239   parameters->errors()->fallback(format, args);
    240   va_end(args);
    241 }
    242 
    243 // Report an error.
    244 
    245 void
    246 gold_error(const char* format, ...)
    247 {
    248   va_list args;
    249   va_start(args, format);
    250   parameters->errors()->error(format, args);
    251   va_end(args);
    252 }
    253 
    254 // Report a warning.
    255 
    256 void
    257 gold_warning(const char* format, ...)
    258 {
    259   va_list args;
    260   va_start(args, format);
    261   parameters->errors()->warning(format, args);
    262   va_end(args);
    263 }
    264 
    265 // Print an informational message.
    266 
    267 void
    268 gold_info(const char* format, ...)
    269 {
    270   va_list args;
    271   va_start(args, format);
    272   parameters->errors()->info(format, args);
    273   va_end(args);
    274 }
    275 
    276 // Report an error at a location.
    277 
    278 template<int size, bool big_endian>
    279 void
    280 gold_error_at_location(const Relocate_info<size, big_endian>* relinfo,
    281 		       size_t relnum, off_t reloffset,
    282 		       const char* format, ...)
    283 {
    284   va_list args;
    285   va_start(args, format);
    286   parameters->errors()->error_at_location(relinfo, relnum, reloffset,
    287 					  format, args);
    288   va_end(args);
    289 }
    290 
    291 // Report a warning at a location.
    292 
    293 template<int size, bool big_endian>
    294 void
    295 gold_warning_at_location(const Relocate_info<size, big_endian>* relinfo,
    296 			 size_t relnum, off_t reloffset,
    297 			 const char* format, ...)
    298 {
    299   va_list args;
    300   va_start(args, format);
    301   parameters->errors()->warning_at_location(relinfo, relnum, reloffset,
    302 					    format, args);
    303   va_end(args);
    304 }
    305 
    306 // Report an undefined symbol.
    307 
    308 void
    309 gold_undefined_symbol(const Symbol* sym)
    310 {
    311   parameters->errors()->undefined_symbol(sym, sym->object()->name().c_str());
    312 }
    313 
    314 // Report an undefined symbol at a reloc location
    315 
    316 template<int size, bool big_endian>
    317 void
    318 gold_undefined_symbol_at_location(const Symbol* sym,
    319 		      const Relocate_info<size, big_endian>* relinfo,
    320 		      size_t relnum, off_t reloffset)
    321 {
    322   parameters->errors()->undefined_symbol(sym,
    323                                          relinfo->location(relnum, reloffset));
    324 }
    325 
    326 #ifdef HAVE_TARGET_32_LITTLE
    327 template
    328 void
    329 gold_error_at_location<32, false>(const Relocate_info<32, false>* relinfo,
    330 				  size_t relnum, off_t reloffset,
    331 				  const char* format, ...);
    332 #endif
    333 
    334 #ifdef HAVE_TARGET_32_BIG
    335 template
    336 void
    337 gold_error_at_location<32, true>(const Relocate_info<32, true>* relinfo,
    338 				 size_t relnum, off_t reloffset,
    339 				 const char* format, ...);
    340 #endif
    341 
    342 #ifdef HAVE_TARGET_64_LITTLE
    343 template
    344 void
    345 gold_error_at_location<64, false>(const Relocate_info<64, false>* relinfo,
    346 				  size_t relnum, off_t reloffset,
    347 				  const char* format, ...);
    348 #endif
    349 
    350 #ifdef HAVE_TARGET_64_BIG
    351 template
    352 void
    353 gold_error_at_location<64, true>(const Relocate_info<64, true>* relinfo,
    354 				 size_t relnum, off_t reloffset,
    355 				 const char* format, ...);
    356 #endif
    357 
    358 #ifdef HAVE_TARGET_32_LITTLE
    359 template
    360 void
    361 gold_warning_at_location<32, false>(const Relocate_info<32, false>* relinfo,
    362 				    size_t relnum, off_t reloffset,
    363 				    const char* format, ...);
    364 #endif
    365 
    366 #ifdef HAVE_TARGET_32_BIG
    367 template
    368 void
    369 gold_warning_at_location<32, true>(const Relocate_info<32, true>* relinfo,
    370 				   size_t relnum, off_t reloffset,
    371 				   const char* format, ...);
    372 #endif
    373 
    374 #ifdef HAVE_TARGET_64_LITTLE
    375 template
    376 void
    377 gold_warning_at_location<64, false>(const Relocate_info<64, false>* relinfo,
    378 				    size_t relnum, off_t reloffset,
    379 				    const char* format, ...);
    380 #endif
    381 
    382 #ifdef HAVE_TARGET_64_BIG
    383 template
    384 void
    385 gold_warning_at_location<64, true>(const Relocate_info<64, true>* relinfo,
    386 				   size_t relnum, off_t reloffset,
    387 				   const char* format, ...);
    388 #endif
    389 
    390 #ifdef HAVE_TARGET_32_LITTLE
    391 template
    392 void
    393 gold_undefined_symbol_at_location<32, false>(
    394     const Symbol* sym,
    395     const Relocate_info<32, false>* relinfo,
    396     size_t relnum, off_t reloffset);
    397 #endif
    398 
    399 #ifdef HAVE_TARGET_32_BIG
    400 template
    401 void
    402 gold_undefined_symbol_at_location<32, true>(
    403     const Symbol* sym,
    404     const Relocate_info<32, true>* relinfo,
    405     size_t relnum, off_t reloffset);
    406 #endif
    407 
    408 #ifdef HAVE_TARGET_64_LITTLE
    409 template
    410 void
    411 gold_undefined_symbol_at_location<64, false>(
    412     const Symbol* sym,
    413     const Relocate_info<64, false>* relinfo,
    414     size_t relnum, off_t reloffset);
    415 #endif
    416 
    417 #ifdef HAVE_TARGET_64_BIG
    418 template
    419 void
    420 gold_undefined_symbol_at_location<64, true>(
    421     const Symbol* sym,
    422     const Relocate_info<64, true>* relinfo,
    423     size_t relnum, off_t reloffset);
    424 #endif
    425 
    426 } // End namespace gold.
    427