1 // errors.cc -- handle errors for gold 2 3 // Copyright 2006, 2007, 2008 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), error_count_(0), 43 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 if (this->lock_ == NULL && parameters->options_valid()) 57 this->lock_ = new Lock; 58 return this->lock_ != NULL; 59 } 60 61 // Increment a counter, holding the lock if available. 62 63 void 64 Errors::increment_counter(int *counter) 65 { 66 if (!this->initialize_lock()) 67 { 68 // The lock does not exist, which means that we don't need it. 69 ++*counter; 70 } 71 else 72 { 73 Hold_lock h(*this->lock_); 74 ++*counter; 75 } 76 } 77 78 // Report a fatal error. 79 80 void 81 Errors::fatal(const char* format, va_list args) 82 { 83 fprintf(stderr, "%s: ", this->program_name_); 84 vfprintf(stderr, format, args); 85 fputc('\n', stderr); 86 gold_exit(false); 87 } 88 89 // Report an error. 90 91 void 92 Errors::error(const char* format, va_list args) 93 { 94 fprintf(stderr, "%s: ", this->program_name_); 95 vfprintf(stderr, format, args); 96 fputc('\n', stderr); 97 98 this->increment_counter(&this->error_count_); 99 } 100 101 // Report a warning. 102 103 void 104 Errors::warning(const char* format, va_list args) 105 { 106 fprintf(stderr, _("%s: warning: "), this->program_name_); 107 vfprintf(stderr, format, args); 108 fputc('\n', stderr); 109 110 this->increment_counter(&this->warning_count_); 111 } 112 113 // Print an informational message. 114 115 void 116 Errors::info(const char* format, va_list args) 117 { 118 vfprintf(stderr, format, args); 119 fputc('\n', stderr); 120 } 121 122 // Report an error at a reloc location. 123 124 template<int size, bool big_endian> 125 void 126 Errors::error_at_location(const Relocate_info<size, big_endian>* relinfo, 127 size_t relnum, off_t reloffset, 128 const char* format, va_list args) 129 { 130 fprintf(stderr, "%s: %s: ", this->program_name_, 131 relinfo->location(relnum, reloffset).c_str()); 132 vfprintf(stderr, format, args); 133 fputc('\n', stderr); 134 135 this->increment_counter(&this->error_count_); 136 } 137 138 // Report a warning at a reloc location. 139 140 template<int size, bool big_endian> 141 void 142 Errors::warning_at_location(const Relocate_info<size, big_endian>* relinfo, 143 size_t relnum, off_t reloffset, 144 const char* format, va_list args) 145 { 146 fprintf(stderr, _("%s: %s: warning: "), this->program_name_, 147 relinfo->location(relnum, reloffset).c_str()); 148 vfprintf(stderr, format, args); 149 fputc('\n', stderr); 150 151 this->increment_counter(&this->warning_count_); 152 } 153 154 // Issue an undefined symbol error. 155 156 template<int size, bool big_endian> 157 void 158 Errors::undefined_symbol(const Symbol* sym, 159 const Relocate_info<size, big_endian>* relinfo, 160 size_t relnum, off_t reloffset) 161 { 162 bool initialized = this->initialize_lock(); 163 gold_assert(initialized); 164 { 165 Hold_lock h(*this->lock_); 166 if (++this->undefined_symbols_[sym] >= max_undefined_error_report) 167 return; 168 ++this->error_count_; 169 } 170 const char* const version = sym->version(); 171 if (version == NULL) 172 fprintf(stderr, _("%s: %s: undefined reference to '%s'\n"), 173 this->program_name_, relinfo->location(relnum, reloffset).c_str(), 174 sym->demangled_name().c_str()); 175 else 176 fprintf(stderr, _("%s: %s: undefined reference to '%s', version '%s'\n"), 177 this->program_name_, relinfo->location(relnum, reloffset).c_str(), 178 sym->demangled_name().c_str(), version); 179 } 180 181 // Issue a debugging message. 182 183 void 184 Errors::debug(const char* format, ...) 185 { 186 fprintf(stderr, _("%s: "), this->program_name_); 187 188 va_list args; 189 va_start(args, format); 190 vfprintf(stderr, format, args); 191 va_end(args); 192 193 fputc('\n', stderr); 194 } 195 196 // The functions which the rest of the code actually calls. 197 198 // Report a fatal error. 199 200 void 201 gold_fatal(const char* format, ...) 202 { 203 va_list args; 204 va_start(args, format); 205 parameters->errors()->fatal(format, args); 206 va_end(args); 207 } 208 209 // Report an error. 210 211 void 212 gold_error(const char* format, ...) 213 { 214 va_list args; 215 va_start(args, format); 216 parameters->errors()->error(format, args); 217 va_end(args); 218 } 219 220 // Report a warning. 221 222 void 223 gold_warning(const char* format, ...) 224 { 225 va_list args; 226 va_start(args, format); 227 parameters->errors()->warning(format, args); 228 va_end(args); 229 } 230 231 // Print an informational message. 232 233 void 234 gold_info(const char* format, ...) 235 { 236 va_list args; 237 va_start(args, format); 238 parameters->errors()->info(format, args); 239 va_end(args); 240 } 241 242 // Report an error at a location. 243 244 template<int size, bool big_endian> 245 void 246 gold_error_at_location(const Relocate_info<size, big_endian>* relinfo, 247 size_t relnum, off_t reloffset, 248 const char* format, ...) 249 { 250 va_list args; 251 va_start(args, format); 252 parameters->errors()->error_at_location(relinfo, relnum, reloffset, 253 format, args); 254 va_end(args); 255 } 256 257 // Report a warning at a location. 258 259 template<int size, bool big_endian> 260 void 261 gold_warning_at_location(const Relocate_info<size, big_endian>* relinfo, 262 size_t relnum, off_t reloffset, 263 const char* format, ...) 264 { 265 va_list args; 266 va_start(args, format); 267 parameters->errors()->warning_at_location(relinfo, relnum, reloffset, 268 format, args); 269 va_end(args); 270 } 271 272 // Report an undefined symbol. 273 274 template<int size, bool big_endian> 275 void 276 gold_undefined_symbol(const Symbol* sym, 277 const Relocate_info<size, big_endian>* relinfo, 278 size_t relnum, off_t reloffset) 279 { 280 parameters->errors()->undefined_symbol(sym, relinfo, relnum, reloffset); 281 } 282 283 #ifdef HAVE_TARGET_32_LITTLE 284 template 285 void 286 gold_error_at_location<32, false>(const Relocate_info<32, false>* relinfo, 287 size_t relnum, off_t reloffset, 288 const char* format, ...); 289 #endif 290 291 #ifdef HAVE_TARGET_32_BIG 292 template 293 void 294 gold_error_at_location<32, true>(const Relocate_info<32, true>* relinfo, 295 size_t relnum, off_t reloffset, 296 const char* format, ...); 297 #endif 298 299 #ifdef HAVE_TARGET_64_LITTLE 300 template 301 void 302 gold_error_at_location<64, false>(const Relocate_info<64, false>* relinfo, 303 size_t relnum, off_t reloffset, 304 const char* format, ...); 305 #endif 306 307 #ifdef HAVE_TARGET_64_BIG 308 template 309 void 310 gold_error_at_location<64, true>(const Relocate_info<64, true>* relinfo, 311 size_t relnum, off_t reloffset, 312 const char* format, ...); 313 #endif 314 315 #ifdef HAVE_TARGET_32_LITTLE 316 template 317 void 318 gold_warning_at_location<32, false>(const Relocate_info<32, false>* relinfo, 319 size_t relnum, off_t reloffset, 320 const char* format, ...); 321 #endif 322 323 #ifdef HAVE_TARGET_32_BIG 324 template 325 void 326 gold_warning_at_location<32, true>(const Relocate_info<32, true>* relinfo, 327 size_t relnum, off_t reloffset, 328 const char* format, ...); 329 #endif 330 331 #ifdef HAVE_TARGET_64_LITTLE 332 template 333 void 334 gold_warning_at_location<64, false>(const Relocate_info<64, false>* relinfo, 335 size_t relnum, off_t reloffset, 336 const char* format, ...); 337 #endif 338 339 #ifdef HAVE_TARGET_64_BIG 340 template 341 void 342 gold_warning_at_location<64, true>(const Relocate_info<64, true>* relinfo, 343 size_t relnum, off_t reloffset, 344 const char* format, ...); 345 #endif 346 347 #ifdef HAVE_TARGET_32_LITTLE 348 template 349 void 350 gold_undefined_symbol<32, false>(const Symbol* sym, 351 const Relocate_info<32, false>* relinfo, 352 size_t relnum, off_t reloffset); 353 #endif 354 355 #ifdef HAVE_TARGET_32_BIG 356 template 357 void 358 gold_undefined_symbol<32, true>(const Symbol* sym, 359 const Relocate_info<32, true>* relinfo, 360 size_t relnum, off_t reloffset); 361 #endif 362 363 #ifdef HAVE_TARGET_64_LITTLE 364 template 365 void 366 gold_undefined_symbol<64, false>(const Symbol* sym, 367 const Relocate_info<64, false>* relinfo, 368 size_t relnum, off_t reloffset); 369 #endif 370 371 #ifdef HAVE_TARGET_64_BIG 372 template 373 void 374 gold_undefined_symbol<64, true>(const Symbol* sym, 375 const Relocate_info<64, true>* relinfo, 376 size_t relnum, off_t reloffset); 377 #endif 378 379 } // End namespace gold. 380