1 // errors.cc -- handle errors for gold 2 3 // Copyright (C) 2006-2020 Free Software Foundation, Inc. 4 // Written by Ian Lance Taylor <iant@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