1// Debugging mode support code -*- C++ -*- 2 3// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 4// Free Software Foundation, Inc. 5// 6// This file is part of the GNU ISO C++ Library. This library is free 7// software; you can redistribute it and/or modify it under the 8// terms of the GNU General Public License as published by the 9// Free Software Foundation; either version 3, or (at your option) 10// any later version. 11 12// This library is distributed in the hope that it will be useful, 13// but WITHOUT ANY WARRANTY; without even the implied warranty of 14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15// GNU General Public License for more details. 16 17// Under Section 7 of GPL version 3, you are granted additional 18// permissions described in the GCC Runtime Library Exception, version 19// 3.1, as published by the Free Software Foundation. 20 21// You should have received a copy of the GNU General Public License and 22// a copy of the GCC Runtime Library Exception along with this program; 23// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24// <http://www.gnu.org/licenses/>. 25 26#include <debug/debug.h> 27#include <debug/safe_sequence.h> 28#include <debug/safe_iterator.h> 29#include <algorithm> 30#include <cassert> 31#include <cstring> 32#include <cctype> 33#include <cstdio> 34#include <cstdlib> 35 36using namespace std; 37 38namespace 39{ 40 __gnu_cxx::__mutex& 41 get_safe_base_mutex() 42 { 43 static __gnu_cxx::__mutex safe_base_mutex; 44 return safe_base_mutex; 45 } 46} // anonymous namespace 47 48namespace __gnu_debug 49{ 50 const char* _S_debug_messages[] = 51 { 52 "function requires a valid iterator range [%1.name;, %2.name;)", 53 "attempt to insert into container with a singular iterator", 54 "attempt to insert into container with an iterator" 55 " from a different container", 56 "attempt to erase from container with a %2.state; iterator", 57 "attempt to erase from container with an iterator" 58 " from a different container", 59 "attempt to subscript container with out-of-bounds index %2;," 60 " but container only holds %3; elements", 61 "attempt to access an element in an empty container", 62 "elements in iterator range [%1.name;, %2.name;)" 63 " are not partitioned by the value %3;", 64 "elements in iterator range [%1.name;, %2.name;)" 65 " are not partitioned by the predicate %3; and value %4;", 66 "elements in iterator range [%1.name;, %2.name;) are not sorted", 67 "elements in iterator range [%1.name;, %2.name;)" 68 " are not sorted according to the predicate %3;", 69 "elements in iterator range [%1.name;, %2.name;) do not form a heap", 70 "elements in iterator range [%1.name;, %2.name;)" 71 " do not form a heap with respect to the predicate %3;", 72 "attempt to write through a singular bitset reference", 73 "attempt to read from a singular bitset reference", 74 "attempt to flip a singular bitset reference", 75 "attempt to splice a list into itself", 76 "attempt to splice lists with inequal allocators", 77 "attempt to splice elements referenced by a %1.state; iterator", 78 "attempt to splice an iterator from a different container", 79 "splice destination %1.name;" 80 " occurs within source range [%2.name;, %3.name;)", 81 "attempt to initialize an iterator that will immediately become singular", 82 "attempt to copy-construct an iterator from a singular iterator", 83 "attempt to construct a constant iterator" 84 " from a singular mutable iterator", 85 "attempt to copy from a singular iterator", 86 "attempt to dereference a %1.state; iterator", 87 "attempt to increment a %1.state; iterator", 88 "attempt to decrement a %1.state; iterator", 89 "attempt to subscript a %1.state; iterator %2; step from" 90 " its current position, which falls outside its dereferenceable range", 91 "attempt to advance a %1.state; iterator %2; steps," 92 " which falls outside its valid range", 93 "attempt to retreat a %1.state; iterator %2; steps," 94 " which falls outside its valid range", 95 "attempt to compare a %1.state; iterator to a %2.state; iterator", 96 "attempt to compare iterators from different sequences", 97 "attempt to order a %1.state; iterator to a %2.state; iterator", 98 "attempt to order iterators from different sequences", 99 "attempt to compute the difference between a %1.state;" 100 " iterator to a %2.state; iterator", 101 "attempt to compute the different between two iterators" 102 " from different sequences", 103 "attempt to dereference an end-of-stream istream_iterator", 104 "attempt to increment an end-of-stream istream_iterator", 105 "attempt to output via an ostream_iterator with no associated stream", 106 "attempt to dereference an end-of-stream istreambuf_iterator" 107 " (this is a GNU extension)", 108 "attempt to increment an end-of-stream istreambuf_iterator" 109 }; 110 111 void 112 _Safe_sequence_base:: 113 _M_detach_all() 114 { 115 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 116 for (_Safe_iterator_base* __iter = _M_iterators; __iter;) 117 { 118 _Safe_iterator_base* __old = __iter; 119 __iter = __iter->_M_next; 120 __old->_M_detach_single(); 121 } 122 123 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;) 124 { 125 _Safe_iterator_base* __old = __iter2; 126 __iter2 = __iter2->_M_next; 127 __old->_M_detach_single(); 128 } 129 } 130 131 void 132 _Safe_sequence_base:: 133 _M_detach_singular() 134 { 135 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 136 for (_Safe_iterator_base* __iter = _M_iterators; __iter;) 137 { 138 _Safe_iterator_base* __old = __iter; 139 __iter = __iter->_M_next; 140 if (__old->_M_singular()) 141 __old->_M_detach_single(); 142 } 143 144 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;) 145 { 146 _Safe_iterator_base* __old = __iter2; 147 __iter2 = __iter2->_M_next; 148 if (__old->_M_singular()) 149 __old->_M_detach_single(); 150 } 151 } 152 153 void 154 _Safe_sequence_base:: 155 _M_revalidate_singular() 156 { 157 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 158 for (_Safe_iterator_base* __iter = _M_iterators; __iter; 159 __iter = __iter->_M_next) 160 __iter->_M_version = _M_version; 161 162 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2; 163 __iter2 = __iter2->_M_next) 164 __iter2->_M_version = _M_version; 165 } 166 167 void 168 _Safe_sequence_base:: 169 _M_swap(_Safe_sequence_base& __x) 170 { 171 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 172 swap(_M_iterators, __x._M_iterators); 173 swap(_M_const_iterators, __x._M_const_iterators); 174 swap(_M_version, __x._M_version); 175 _Safe_iterator_base* __iter; 176 for (__iter = _M_iterators; __iter; __iter = __iter->_M_next) 177 __iter->_M_sequence = this; 178 for (__iter = __x._M_iterators; __iter; __iter = __iter->_M_next) 179 __iter->_M_sequence = &__x; 180 for (__iter = _M_const_iterators; __iter; __iter = __iter->_M_next) 181 __iter->_M_sequence = this; 182 for (__iter = __x._M_const_iterators; __iter; __iter = __iter->_M_next) 183 __iter->_M_sequence = &__x; 184 } 185 186 __gnu_cxx::__mutex& 187 _Safe_sequence_base:: 188 _M_get_mutex() throw () 189 { return get_safe_base_mutex(); } 190 191 void 192 _Safe_iterator_base:: 193 _M_attach(_Safe_sequence_base* __seq, bool __constant) 194 { 195 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 196 _M_attach_single(__seq, __constant); 197 } 198 199 void 200 _Safe_iterator_base:: 201 _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw () 202 { 203 _M_detach_single(); 204 205 // Attach to the new sequence (if there is one) 206 if (__seq) 207 { 208 _M_sequence = __seq; 209 _M_version = _M_sequence->_M_version; 210 _M_prior = 0; 211 if (__constant) 212 { 213 _M_next = _M_sequence->_M_const_iterators; 214 if (_M_next) 215 _M_next->_M_prior = this; 216 _M_sequence->_M_const_iterators = this; 217 } 218 else 219 { 220 _M_next = _M_sequence->_M_iterators; 221 if (_M_next) 222 _M_next->_M_prior = this; 223 _M_sequence->_M_iterators = this; 224 } 225 } 226 } 227 228 void 229 _Safe_iterator_base:: 230 _M_detach() 231 { 232 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 233 _M_detach_single(); 234 } 235 236 void 237 _Safe_iterator_base:: 238 _M_detach_single() throw () 239 { 240 if (_M_sequence) 241 { 242 // Remove us from this sequence's list 243 if (_M_prior) 244 _M_prior->_M_next = _M_next; 245 if (_M_next) 246 _M_next->_M_prior = _M_prior; 247 248 if (_M_sequence->_M_const_iterators == this) 249 _M_sequence->_M_const_iterators = _M_next; 250 if (_M_sequence->_M_iterators == this) 251 _M_sequence->_M_iterators = _M_next; 252 } 253 254 _M_sequence = 0; 255 _M_version = 0; 256 _M_prior = 0; 257 _M_next = 0; 258 } 259 260 bool 261 _Safe_iterator_base:: 262 _M_singular() const throw () 263 { return !_M_sequence || _M_version != _M_sequence->_M_version; } 264 265 bool 266 _Safe_iterator_base:: 267 _M_can_compare(const _Safe_iterator_base& __x) const throw () 268 { 269 return (!_M_singular() 270 && !__x._M_singular() && _M_sequence == __x._M_sequence); 271 } 272 273 __gnu_cxx::__mutex& 274 _Safe_iterator_base:: 275 _M_get_mutex() throw () 276 { return get_safe_base_mutex(); } 277 278 void 279 _Error_formatter::_Parameter:: 280 _M_print_field(const _Error_formatter* __formatter, const char* __name) const 281 { 282 assert(this->_M_kind != _Parameter::__unused_param); 283 const int __bufsize = 64; 284 char __buf[__bufsize]; 285 286 if (_M_kind == __iterator) 287 { 288 if (strcmp(__name, "name") == 0) 289 { 290 assert(_M_variant._M_iterator._M_name); 291 __formatter->_M_print_word(_M_variant._M_iterator._M_name); 292 } 293 else if (strcmp(__name, "address") == 0) 294 { 295 __formatter->_M_format_word(__buf, __bufsize, "%p", 296 _M_variant._M_iterator._M_address); 297 __formatter->_M_print_word(__buf); 298 } 299 else if (strcmp(__name, "type") == 0) 300 { 301 if (!_M_variant._M_iterator._M_type) 302 __formatter->_M_print_word("<unknown type>"); 303 else 304 // TBD: demangle! 305 __formatter->_M_print_word(_M_variant._M_iterator. 306 _M_type->name()); 307 } 308 else if (strcmp(__name, "constness") == 0) 309 { 310 static const char* __constness_names[__last_constness] = 311 { 312 "<unknown>", 313 "constant", 314 "mutable" 315 }; 316 __formatter->_M_print_word(__constness_names[_M_variant. 317 _M_iterator. 318 _M_constness]); 319 } 320 else if (strcmp(__name, "state") == 0) 321 { 322 static const char* __state_names[__last_state] = 323 { 324 "<unknown>", 325 "singular", 326 "dereferenceable (start-of-sequence)", 327 "dereferenceable", 328 "past-the-end" 329 }; 330 __formatter->_M_print_word(__state_names[_M_variant. 331 _M_iterator._M_state]); 332 } 333 else if (strcmp(__name, "sequence") == 0) 334 { 335 assert(_M_variant._M_iterator._M_sequence); 336 __formatter->_M_format_word(__buf, __bufsize, "%p", 337 _M_variant._M_iterator._M_sequence); 338 __formatter->_M_print_word(__buf); 339 } 340 else if (strcmp(__name, "seq_type") == 0) 341 { 342 if (!_M_variant._M_iterator._M_seq_type) 343 __formatter->_M_print_word("<unknown seq_type>"); 344 else 345 // TBD: demangle! 346 __formatter->_M_print_word(_M_variant._M_iterator. 347 _M_seq_type->name()); 348 } 349 else 350 assert(false); 351 } 352 else if (_M_kind == __sequence) 353 { 354 if (strcmp(__name, "name") == 0) 355 { 356 assert(_M_variant._M_sequence._M_name); 357 __formatter->_M_print_word(_M_variant._M_sequence._M_name); 358 } 359 else if (strcmp(__name, "address") == 0) 360 { 361 assert(_M_variant._M_sequence._M_address); 362 __formatter->_M_format_word(__buf, __bufsize, "%p", 363 _M_variant._M_sequence._M_address); 364 __formatter->_M_print_word(__buf); 365 } 366 else if (strcmp(__name, "type") == 0) 367 { 368 if (!_M_variant._M_sequence._M_type) 369 __formatter->_M_print_word("<unknown type>"); 370 else 371 // TBD: demangle! 372 __formatter->_M_print_word(_M_variant._M_sequence. 373 _M_type->name()); 374 } 375 else 376 assert(false); 377 } 378 else if (_M_kind == __integer) 379 { 380 if (strcmp(__name, "name") == 0) 381 { 382 assert(_M_variant._M_integer._M_name); 383 __formatter->_M_print_word(_M_variant._M_integer._M_name); 384 } 385 else 386 assert(false); 387 } 388 else if (_M_kind == __string) 389 { 390 if (strcmp(__name, "name") == 0) 391 { 392 assert(_M_variant._M_string._M_name); 393 __formatter->_M_print_word(_M_variant._M_string._M_name); 394 } 395 else 396 assert(false); 397 } 398 else 399 { 400 assert(false); 401 } 402 } 403 404 void 405 _Error_formatter::_Parameter:: 406 _M_print_description(const _Error_formatter* __formatter) const 407 { 408 const int __bufsize = 128; 409 char __buf[__bufsize]; 410 411 if (_M_kind == __iterator) 412 { 413 __formatter->_M_print_word("iterator "); 414 if (_M_variant._M_iterator._M_name) 415 { 416 __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ", 417 _M_variant._M_iterator._M_name); 418 __formatter->_M_print_word(__buf); 419 } 420 421 __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n", 422 _M_variant._M_iterator._M_address); 423 __formatter->_M_print_word(__buf); 424 if (_M_variant._M_iterator._M_type) 425 { 426 __formatter->_M_print_word("type = "); 427 _M_print_field(__formatter, "type"); 428 429 if (_M_variant._M_iterator._M_constness != __unknown_constness) 430 { 431 __formatter->_M_print_word(" ("); 432 _M_print_field(__formatter, "constness"); 433 __formatter->_M_print_word(" iterator)"); 434 } 435 __formatter->_M_print_word(";\n"); 436 } 437 438 if (_M_variant._M_iterator._M_state != __unknown_state) 439 { 440 __formatter->_M_print_word(" state = "); 441 _M_print_field(__formatter, "state"); 442 __formatter->_M_print_word(";\n"); 443 } 444 445 if (_M_variant._M_iterator._M_sequence) 446 { 447 __formatter->_M_print_word(" references sequence "); 448 if (_M_variant._M_iterator._M_seq_type) 449 { 450 __formatter->_M_print_word("with type `"); 451 _M_print_field(__formatter, "seq_type"); 452 __formatter->_M_print_word("' "); 453 } 454 455 __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p\n", 456 _M_variant._M_sequence._M_address); 457 __formatter->_M_print_word(__buf); 458 } 459 __formatter->_M_print_word("}\n"); 460 } 461 else if (_M_kind == __sequence) 462 { 463 __formatter->_M_print_word("sequence "); 464 if (_M_variant._M_sequence._M_name) 465 { 466 __formatter->_M_format_word(__buf, __bufsize, "\"%s\" ", 467 _M_variant._M_sequence._M_name); 468 __formatter->_M_print_word(__buf); 469 } 470 471 __formatter->_M_format_word(__buf, __bufsize, "@ 0x%p {\n", 472 _M_variant._M_sequence._M_address); 473 __formatter->_M_print_word(__buf); 474 475 if (_M_variant._M_sequence._M_type) 476 { 477 __formatter->_M_print_word(" type = "); 478 _M_print_field(__formatter, "type"); 479 __formatter->_M_print_word(";\n"); 480 } 481 __formatter->_M_print_word("}\n"); 482 } 483 } 484 485 const _Error_formatter& 486 _Error_formatter::_M_message(_Debug_msg_id __id) const throw () 487 { return this->_M_message(_S_debug_messages[__id]); } 488 489 void 490 _Error_formatter::_M_error() const 491 { 492 const int __bufsize = 128; 493 char __buf[__bufsize]; 494 495 // Emit file & line number information 496 _M_column = 1; 497 _M_wordwrap = false; 498 if (_M_file) 499 { 500 _M_format_word(__buf, __bufsize, "%s:", _M_file); 501 _M_print_word(__buf); 502 _M_column += strlen(__buf); 503 } 504 505 if (_M_line > 0) 506 { 507 _M_format_word(__buf, __bufsize, "%u:", _M_line); 508 _M_print_word(__buf); 509 _M_column += strlen(__buf); 510 } 511 512 if (_M_max_length) 513 _M_wordwrap = true; 514 _M_print_word("error: "); 515 516 // Print the error message 517 assert(_M_text); 518 _M_print_string(_M_text); 519 _M_print_word(".\n"); 520 521 // Emit descriptions of the objects involved in the operation 522 _M_wordwrap = false; 523 bool __has_noninteger_parameters = false; 524 for (unsigned int __i = 0; __i < _M_num_parameters; ++__i) 525 { 526 if (_M_parameters[__i]._M_kind == _Parameter::__iterator 527 || _M_parameters[__i]._M_kind == _Parameter::__sequence) 528 { 529 if (!__has_noninteger_parameters) 530 { 531 _M_first_line = true; 532 _M_print_word("\nObjects involved in the operation:\n"); 533 __has_noninteger_parameters = true; 534 } 535 _M_parameters[__i]._M_print_description(this); 536 } 537 } 538 539 abort(); 540 } 541 542 template<typename _Tp> 543 void 544 _Error_formatter::_M_format_word(char* __buf, 545 int __n __attribute__ ((__unused__)), 546 const char* __fmt, _Tp __s) const throw () 547 { 548#ifdef _GLIBCXX_USE_C99 549 std::snprintf(__buf, __n, __fmt, __s); 550#else 551 std::sprintf(__buf, __fmt, __s); 552#endif 553 } 554 555 556 void 557 _Error_formatter::_M_print_word(const char* __word) const 558 { 559 if (!_M_wordwrap) 560 { 561 fprintf(stderr, "%s", __word); 562 return; 563 } 564 565 size_t __length = strlen(__word); 566 if (__length == 0) 567 return; 568 569 if ((_M_column + __length < _M_max_length) 570 || (__length >= _M_max_length && _M_column == 1)) 571 { 572 // If this isn't the first line, indent 573 if (_M_column == 1 && !_M_first_line) 574 { 575 char __spacing[_M_indent + 1]; 576 for (int i = 0; i < _M_indent; ++i) 577 __spacing[i] = ' '; 578 __spacing[_M_indent] = '\0'; 579 fprintf(stderr, "%s", __spacing); 580 _M_column += _M_indent; 581 } 582 583 fprintf(stderr, "%s", __word); 584 _M_column += __length; 585 586 if (__word[__length - 1] == '\n') 587 { 588 _M_first_line = false; 589 _M_column = 1; 590 } 591 } 592 else 593 { 594 _M_column = 1; 595 _M_print_word("\n"); 596 _M_print_word(__word); 597 } 598 } 599 600 void 601 _Error_formatter:: 602 _M_print_string(const char* __string) const 603 { 604 const char* __start = __string; 605 const char* __finish = __start; 606 const int __bufsize = 128; 607 char __buf[__bufsize]; 608 609 while (*__start) 610 { 611 if (*__start != '%') 612 { 613 // [__start, __finish) denotes the next word 614 __finish = __start; 615 while (isalnum(*__finish)) 616 ++__finish; 617 if (__start == __finish) 618 ++__finish; 619 if (isspace(*__finish)) 620 ++__finish; 621 622 const ptrdiff_t __len = __finish - __start; 623 assert(__len < __bufsize); 624 memcpy(__buf, __start, __len); 625 __buf[__len] = '\0'; 626 _M_print_word(__buf); 627 __start = __finish; 628 629 // Skip extra whitespace 630 while (*__start == ' ') 631 ++__start; 632 633 continue; 634 } 635 636 ++__start; 637 assert(*__start); 638 if (*__start == '%') 639 { 640 _M_print_word("%"); 641 ++__start; 642 continue; 643 } 644 645 // Get the parameter number 646 assert(*__start >= '1' && *__start <= '9'); 647 size_t __param = *__start - '0'; 648 --__param; 649 assert(__param < _M_num_parameters); 650 651 // '.' separates the parameter number from the field 652 // name, if there is one. 653 ++__start; 654 if (*__start != '.') 655 { 656 assert(*__start == ';'); 657 ++__start; 658 __buf[0] = '\0'; 659 if (_M_parameters[__param]._M_kind == _Parameter::__integer) 660 { 661 _M_format_word(__buf, __bufsize, "%ld", 662 _M_parameters[__param]._M_variant._M_integer._M_value); 663 _M_print_word(__buf); 664 } 665 else if (_M_parameters[__param]._M_kind == _Parameter::__string) 666 _M_print_string(_M_parameters[__param]._M_variant._M_string._M_value); 667 continue; 668 } 669 670 // Extract the field name we want 671 enum { __max_field_len = 16 }; 672 char __field[__max_field_len]; 673 int __field_idx = 0; 674 ++__start; 675 while (*__start != ';') 676 { 677 assert(*__start); 678 assert(__field_idx < __max_field_len-1); 679 __field[__field_idx++] = *__start++; 680 } 681 ++__start; 682 __field[__field_idx] = 0; 683 684 _M_parameters[__param]._M_print_field(this, __field); 685 } 686 } 687 688 void 689 _Error_formatter::_M_get_max_length() const throw () 690 { 691 const char* __nptr = std::getenv("GLIBCXX_DEBUG_MESSAGE_LENGTH"); 692 if (__nptr) 693 { 694 char* __endptr; 695 const unsigned long __ret = std::strtoul(__nptr, &__endptr, 0); 696 if (*__nptr != '\0' && *__endptr == '\0') 697 _M_max_length = __ret; 698 } 699 } 700 701 // Instantiations. 702 template 703 void 704 _Error_formatter::_M_format_word(char*, int, const char*, 705 const void*) const; 706 707 template 708 void 709 _Error_formatter::_M_format_word(char*, int, const char*, long) const; 710 711 template 712 void 713 _Error_formatter::_M_format_word(char*, int, const char*, 714 std::size_t) const; 715 716 template 717 void 718 _Error_formatter::_M_format_word(char*, int, const char*, 719 const char*) const; 720} // namespace __gnu_debug 721