1 // errors.cc -- handle errors for gold 2 3 // Copyright (C) 2006-2022 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 // Print a trace message. 132 133 void 134 Errors::trace(const char* format, va_list args) 135 { 136 vfprintf(stdout, format, args); 137 fputc('\n', stdout); 138 } 139 140 // Report an error at a reloc location. 141 142 template<int size, bool big_endian> 143 void 144 Errors::error_at_location(const Relocate_info<size, big_endian>* relinfo, 145 size_t relnum, off_t reloffset, 146 const char* format, va_list args) 147 { 148 fprintf(stderr, _("%s: error: "), 149 relinfo->location(relnum, reloffset).c_str()); 150 vfprintf(stderr, format, args); 151 fputc('\n', stderr); 152 153 this->increment_counter(&this->error_count_); 154 } 155 156 // Report a warning at a reloc location. 157 158 template<int size, bool big_endian> 159 void 160 Errors::warning_at_location(const Relocate_info<size, big_endian>* relinfo, 161 size_t relnum, off_t reloffset, 162 const char* format, va_list args) 163 { 164 fprintf(stderr, _("%s: warning: "), 165 relinfo->location(relnum, reloffset).c_str()); 166 vfprintf(stderr, format, args); 167 fputc('\n', stderr); 168 169 this->increment_counter(&this->warning_count_); 170 } 171 172 // Issue an undefined symbol error with a caller-supplied location string. 173 174 void 175 Errors::undefined_symbol(const Symbol* sym, const std::string& location) 176 { 177 bool initialized = this->initialize_lock(); 178 gold_assert(initialized); 179 180 const char* zmsg; 181 { 182 Hold_lock h(*this->lock_); 183 if (++this->undefined_symbols_[sym] >= max_undefined_error_report) 184 return; 185 if (parameters->options().warn_unresolved_symbols()) 186 { 187 ++this->warning_count_; 188 zmsg = _("warning"); 189 } 190 else 191 { 192 ++this->error_count_; 193 zmsg = _("error"); 194 } 195 } 196 197 const char* const version = sym->version(); 198 if (version == NULL) 199 fprintf(stderr, _("%s: %s: undefined reference to '%s'\n"), 200 location.c_str(), zmsg, sym->demangled_name().c_str()); 201 else 202 fprintf(stderr, 203 _("%s: %s: undefined reference to '%s', version '%s'\n"), 204 location.c_str(), zmsg, sym->demangled_name().c_str(), version); 205 206 if (sym->is_cxx_vtable()) 207 gold_info(_("%s: the vtable symbol may be undefined because " 208 "the class is missing its key function"), 209 program_name); 210 if (sym->is_placeholder()) 211 gold_info(_("%s: the symbol should have been defined by a plugin"), 212 program_name); 213 } 214 215 // Issue a debugging message. 216 217 void 218 Errors::debug(const char* format, ...) 219 { 220 fprintf(stderr, _("%s: "), this->program_name_); 221 222 va_list args; 223 va_start(args, format); 224 vfprintf(stderr, format, args); 225 va_end(args); 226 227 fputc('\n', stderr); 228 } 229 230 // The functions which the rest of the code actually calls. 231 232 // Report a fatal error. 233 234 void 235 gold_fatal(const char* format, ...) 236 { 237 va_list args; 238 va_start(args, format); 239 parameters->errors()->fatal(format, args); 240 va_end(args); 241 } 242 243 // Report a fallback error. 244 245 void 246 gold_fallback(const char* format, ...) 247 { 248 va_list args; 249 va_start(args, format); 250 parameters->errors()->fallback(format, args); 251 va_end(args); 252 } 253 254 // Report an error. 255 256 void 257 gold_error(const char* format, ...) 258 { 259 va_list args; 260 va_start(args, format); 261 parameters->errors()->error(format, args); 262 va_end(args); 263 } 264 265 // Report a warning. 266 267 void 268 gold_warning(const char* format, ...) 269 { 270 va_list args; 271 va_start(args, format); 272 parameters->errors()->warning(format, args); 273 va_end(args); 274 } 275 276 // Print an informational message. 277 278 void 279 gold_info(const char* format, ...) 280 { 281 va_list args; 282 va_start(args, format); 283 parameters->errors()->info(format, args); 284 va_end(args); 285 } 286 287 // Print a trace message (to stdout). 288 289 void 290 gold_trace(const char* format, ...) 291 { 292 va_list args; 293 va_start(args, format); 294 parameters->errors()->trace(format, args); 295 va_end(args); 296 } 297 298 // Report an error at a location. 299 300 template<int size, bool big_endian> 301 void 302 gold_error_at_location(const Relocate_info<size, big_endian>* relinfo, 303 size_t relnum, off_t reloffset, 304 const char* format, ...) 305 { 306 va_list args; 307 va_start(args, format); 308 parameters->errors()->error_at_location(relinfo, relnum, reloffset, 309 format, args); 310 va_end(args); 311 } 312 313 // Report a warning at a location. 314 315 template<int size, bool big_endian> 316 void 317 gold_warning_at_location(const Relocate_info<size, big_endian>* relinfo, 318 size_t relnum, off_t reloffset, 319 const char* format, ...) 320 { 321 va_list args; 322 va_start(args, format); 323 parameters->errors()->warning_at_location(relinfo, relnum, reloffset, 324 format, args); 325 va_end(args); 326 } 327 328 // Report an undefined symbol. 329 330 void 331 gold_undefined_symbol(const Symbol* sym) 332 { 333 parameters->errors()->undefined_symbol(sym, sym->object()->name().c_str()); 334 } 335 336 // Report an undefined symbol at a reloc location 337 338 template<int size, bool big_endian> 339 void 340 gold_undefined_symbol_at_location(const Symbol* sym, 341 const Relocate_info<size, big_endian>* relinfo, 342 size_t relnum, off_t reloffset) 343 { 344 parameters->errors()->undefined_symbol(sym, 345 relinfo->location(relnum, reloffset)); 346 } 347 348 #ifdef HAVE_TARGET_32_LITTLE 349 template 350 void 351 gold_error_at_location<32, false>(const Relocate_info<32, false>* relinfo, 352 size_t relnum, off_t reloffset, 353 const char* format, ...); 354 #endif 355 356 #ifdef HAVE_TARGET_32_BIG 357 template 358 void 359 gold_error_at_location<32, true>(const Relocate_info<32, true>* relinfo, 360 size_t relnum, off_t reloffset, 361 const char* format, ...); 362 #endif 363 364 #ifdef HAVE_TARGET_64_LITTLE 365 template 366 void 367 gold_error_at_location<64, false>(const Relocate_info<64, false>* relinfo, 368 size_t relnum, off_t reloffset, 369 const char* format, ...); 370 #endif 371 372 #ifdef HAVE_TARGET_64_BIG 373 template 374 void 375 gold_error_at_location<64, true>(const Relocate_info<64, true>* relinfo, 376 size_t relnum, off_t reloffset, 377 const char* format, ...); 378 #endif 379 380 #ifdef HAVE_TARGET_32_LITTLE 381 template 382 void 383 gold_warning_at_location<32, false>(const Relocate_info<32, false>* relinfo, 384 size_t relnum, off_t reloffset, 385 const char* format, ...); 386 #endif 387 388 #ifdef HAVE_TARGET_32_BIG 389 template 390 void 391 gold_warning_at_location<32, true>(const Relocate_info<32, true>* relinfo, 392 size_t relnum, off_t reloffset, 393 const char* format, ...); 394 #endif 395 396 #ifdef HAVE_TARGET_64_LITTLE 397 template 398 void 399 gold_warning_at_location<64, false>(const Relocate_info<64, false>* relinfo, 400 size_t relnum, off_t reloffset, 401 const char* format, ...); 402 #endif 403 404 #ifdef HAVE_TARGET_64_BIG 405 template 406 void 407 gold_warning_at_location<64, true>(const Relocate_info<64, true>* relinfo, 408 size_t relnum, off_t reloffset, 409 const char* format, ...); 410 #endif 411 412 #ifdef HAVE_TARGET_32_LITTLE 413 template 414 void 415 gold_undefined_symbol_at_location<32, false>( 416 const Symbol* sym, 417 const Relocate_info<32, false>* relinfo, 418 size_t relnum, off_t reloffset); 419 #endif 420 421 #ifdef HAVE_TARGET_32_BIG 422 template 423 void 424 gold_undefined_symbol_at_location<32, true>( 425 const Symbol* sym, 426 const Relocate_info<32, true>* relinfo, 427 size_t relnum, off_t reloffset); 428 #endif 429 430 #ifdef HAVE_TARGET_64_LITTLE 431 template 432 void 433 gold_undefined_symbol_at_location<64, false>( 434 const Symbol* sym, 435 const Relocate_info<64, false>* relinfo, 436 size_t relnum, off_t reloffset); 437 #endif 438 439 #ifdef HAVE_TARGET_64_BIG 440 template 441 void 442 gold_undefined_symbol_at_location<64, true>( 443 const Symbol* sym, 444 const Relocate_info<64, true>* relinfo, 445 size_t relnum, off_t reloffset); 446 #endif 447 448 } // End namespace gold. 449