errors.cc 10 KB

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