1 // Debugging mode support code -*- C++ -*- 2 3 // Copyright (C) 2003-2022 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 #include <bits/move.h> 26 #include <bits/stl_iterator_base_types.h> 27 28 #include <debug/formatter.h> 29 #include <debug/safe_base.h> 30 #include <debug/safe_unordered_base.h> 31 #include <debug/safe_iterator.h> 32 #include <debug/safe_local_iterator.h> 33 #include <debug/vector> 34 35 #include <cassert> 36 #include <cstdio> // for std::fprintf, stderr 37 #include <cstdlib> // for std::abort 38 #include <cctype> // for std::isspace. 39 #include <cstring> // for std::strstr. 40 41 #include <algorithm> // for std::min. 42 43 #include <cxxabi.h> // for __cxa_demangle. 44 45 #include "mutex_pool.h" 46 47 #ifdef _GLIBCXX_VERBOSE_ASSERT 48 namespace std 49 { 50 [[__noreturn__]] 51 void 52 __glibcxx_assert_fail(const char* file, int line, 53 const char* function, const char* condition) noexcept 54 { 55 if (file && function && condition) 56 fprintf(stderr, "%s:%d: %s: Assertion '%s' failed.\n", 57 file, line, function, condition); 58 else if (function) 59 fprintf(stderr, "%s: Undefined behavior detected.\n", function); 60 abort(); 61 } 62 } 63 #endif 64 65 using namespace std; 66 67 namespace 68 { 69 /** Returns different instances of __mutex depending on the passed address 70 * in order to limit contention without breaking current library binary 71 * compatibility. */ 72 __gnu_cxx::__mutex& 73 get_safe_base_mutex(void* address) 74 { 75 // Use arbitrarily __gnu_debug::vector<int> as the container giving 76 // alignment of debug containers. 77 const auto alignbits = __builtin_ctz(alignof(__gnu_debug::vector<int>)); 78 const unsigned char index 79 = (reinterpret_cast<std::size_t>(address) >> alignbits) 80 & __gnu_internal::mask; 81 return __gnu_internal::get_mutex(index); 82 } 83 84 #pragma GCC diagnostic push 85 // Suppress -Wabi=2 warnings due to PR c++/51322 mangling change 86 #pragma GCC diagnostic warning "-Wabi=6" 87 88 void 89 swap_its(__gnu_debug::_Safe_sequence_base& __lhs, 90 __gnu_debug::_Safe_iterator_base*& __lhs_its, 91 __gnu_debug::_Safe_sequence_base& __rhs, 92 __gnu_debug::_Safe_iterator_base*& __rhs_its) 93 { 94 swap(__lhs_its, __rhs_its); 95 __gnu_debug::_Safe_iterator_base* __iter; 96 for (__iter = __rhs_its; __iter; __iter = __iter->_M_next) 97 __iter->_M_sequence = &__rhs; 98 for (__iter = __lhs_its; __iter; __iter = __iter->_M_next) 99 __iter->_M_sequence = &__lhs; 100 } 101 102 void 103 swap_seq_single(__gnu_debug::_Safe_sequence_base& __lhs, 104 __gnu_debug::_Safe_sequence_base& __rhs) 105 { 106 swap(__lhs._M_version, __rhs._M_version); 107 swap_its(__lhs, __lhs._M_iterators, 108 __rhs, __rhs._M_iterators); 109 swap_its(__lhs, __lhs._M_const_iterators, 110 __rhs, __rhs._M_const_iterators); 111 } 112 #pragma GCC diagnostic pop 113 114 template<typename _Action> 115 void 116 lock_and_run(__gnu_cxx::__mutex& lhs_mutex, __gnu_cxx::__mutex& rhs_mutex, 117 _Action action) 118 { 119 // We need to lock both sequences to run action. 120 if (&lhs_mutex == &rhs_mutex) 121 { 122 __gnu_cxx::__scoped_lock sentry(lhs_mutex); 123 action(); 124 } 125 else 126 { 127 __gnu_cxx::__scoped_lock sentry1(&lhs_mutex < &rhs_mutex 128 ? lhs_mutex : rhs_mutex); 129 __gnu_cxx::__scoped_lock sentry2(&lhs_mutex < &rhs_mutex 130 ? rhs_mutex : lhs_mutex); 131 action(); 132 } 133 } 134 135 void 136 swap_seq(__gnu_cxx::__mutex& lhs_mutex, 137 __gnu_debug::_Safe_sequence_base& lhs, 138 __gnu_cxx::__mutex& rhs_mutex, 139 __gnu_debug::_Safe_sequence_base& rhs) 140 { 141 lock_and_run(lhs_mutex, rhs_mutex, 142 [&lhs, &rhs]() { swap_seq_single(lhs, rhs); }); 143 } 144 145 void 146 swap_ucont_single(__gnu_debug::_Safe_unordered_container_base& __lhs, 147 __gnu_debug::_Safe_unordered_container_base& __rhs) 148 { 149 swap_seq_single(__lhs, __rhs); 150 swap_its(__lhs, __lhs._M_local_iterators, 151 __rhs, __rhs._M_local_iterators); 152 swap_its(__lhs, __lhs._M_const_local_iterators, 153 __rhs, __rhs._M_const_local_iterators); 154 } 155 156 void 157 swap_ucont(__gnu_cxx::__mutex& lhs_mutex, 158 __gnu_debug::_Safe_unordered_container_base& lhs, 159 __gnu_cxx::__mutex& rhs_mutex, 160 __gnu_debug::_Safe_unordered_container_base& rhs) 161 { 162 lock_and_run(lhs_mutex, rhs_mutex, 163 [&lhs, &rhs]() { swap_ucont_single(lhs, rhs); }); 164 } 165 166 void 167 detach_all(__gnu_debug::_Safe_iterator_base* __iter) 168 { 169 for (; __iter;) 170 { 171 __gnu_debug::_Safe_iterator_base* __old = __iter; 172 __iter = __iter->_M_next; 173 __old->_M_reset(); 174 } 175 } 176 } // anonymous namespace 177 178 namespace __gnu_debug 179 { 180 const char* const _S_debug_messages[] = 181 { 182 // General Checks 183 "function requires a valid iterator range [%1.name;, %2.name;)", 184 "attempt to insert into container with a singular iterator", 185 "attempt to insert into container with an iterator" 186 " from a different container", 187 "attempt to erase from container with a %2.state; iterator", 188 "attempt to erase from container with an iterator" 189 " from a different container", 190 "attempt to subscript container with out-of-bounds index %2;," 191 " but container only holds %3; elements", 192 "attempt to access an element in an empty container", 193 "elements in iterator range [%1.name;, %2.name;)" 194 " are not partitioned by the value %3;", 195 "elements in iterator range [%1.name;, %2.name;)" 196 " are not partitioned by the predicate %3; and value %4;", 197 "elements in iterator range [%1.name;, %2.name;) are not sorted", 198 "elements in iterator range [%1.name;, %2.name;)" 199 " are not sorted according to the predicate %3;", 200 "elements in iterator range [%1.name;, %2.name;) do not form a heap", 201 "elements in iterator range [%1.name;, %2.name;)" 202 " do not form a heap with respect to the predicate %3;", 203 // std::bitset checks 204 "attempt to write through a singular bitset reference", 205 "attempt to read from a singular bitset reference", 206 "attempt to flip a singular bitset reference", 207 // std::list checks 208 "attempt to splice a list into itself", 209 "attempt to splice lists with unequal allocators", 210 "attempt to splice elements referenced by a %1.state; iterator", 211 "attempt to splice an iterator from a different container", 212 "splice destination %1.name;" 213 " occurs within source range [%2.name;, %3.name;)", 214 // iterator checks 215 "attempt to initialize an iterator that will immediately become singular", 216 "attempt to copy-construct an iterator from a singular iterator", 217 "attempt to construct a constant iterator" 218 " from a singular mutable iterator", 219 "attempt to copy from a singular iterator", 220 "attempt to dereference a %1.state; iterator", 221 "attempt to increment a %1.state; iterator", 222 "attempt to decrement a %1.state; iterator", 223 "attempt to subscript a %1.state; iterator %2; step from" 224 " its current position, which falls outside its dereferenceable range", 225 "attempt to advance a %1.state; iterator %2; steps," 226 " which falls outside its valid range", 227 "attempt to retreat a %1.state; iterator %2; steps," 228 " which falls outside its valid range", 229 "attempt to compare a %1.state; iterator to a %2.state; iterator", 230 "attempt to compare iterators from different sequences", 231 "attempt to order a %1.state; iterator to a %2.state; iterator", 232 "attempt to order iterators from different sequences", 233 "attempt to compute the difference between a %1.state;" 234 " iterator to a %2.state; iterator", 235 "attempt to compute the different between two iterators" 236 " from different sequences", 237 // istream_iterator 238 "attempt to dereference an end-of-stream istream_iterator", 239 "attempt to increment an end-of-stream istream_iterator", 240 // ostream_iterator 241 "attempt to output via an ostream_iterator with no associated stream", 242 // istreambuf_iterator 243 "attempt to dereference an end-of-stream istreambuf_iterator" 244 " (this is a GNU extension)", 245 "attempt to increment an end-of-stream istreambuf_iterator", 246 // std::forward_list 247 "attempt to insert into container after an end iterator", 248 "attempt to erase from container after a %2.state; iterator not followed" 249 " by a dereferenceable one", 250 "function requires a valid iterator range (%2.name;, %3.name;)" 251 ", \"%2.name;\" shall be before and not equal to \"%3.name;\"", 252 // std::unordered_container::local_iterator 253 "attempt to compare local iterators from different unordered container" 254 " buckets", 255 "function requires a non-empty iterator range [%1.name;, %2.name;)", 256 "attempt to self move assign", 257 "attempt to access container with out-of-bounds bucket index %2;," 258 " container only holds %3; buckets", 259 "load factor shall be positive", 260 "allocators must be equal", 261 "attempt to insert with an iterator range [%1.name;, %2.name;) from this" 262 " container", 263 "comparison doesn't meet irreflexive requirements, assert(!(a < a))" 264 }; 265 266 void 267 _Safe_sequence_base:: 268 _M_detach_all() 269 { 270 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 271 detach_all(_M_iterators); 272 _M_iterators = 0; 273 274 detach_all(_M_const_iterators); 275 _M_const_iterators = 0; 276 } 277 278 void 279 _Safe_sequence_base:: 280 _M_detach_singular() 281 { 282 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 283 for (_Safe_iterator_base* __iter = _M_iterators; __iter;) 284 { 285 _Safe_iterator_base* __old = __iter; 286 __iter = __iter->_M_next; 287 if (__old->_M_singular()) 288 __old->_M_detach_single(); 289 } 290 291 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;) 292 { 293 _Safe_iterator_base* __old = __iter2; 294 __iter2 = __iter2->_M_next; 295 if (__old->_M_singular()) 296 __old->_M_detach_single(); 297 } 298 } 299 300 void 301 _Safe_sequence_base:: 302 _M_revalidate_singular() 303 { 304 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 305 for (_Safe_iterator_base* __iter = _M_iterators; __iter; 306 __iter = __iter->_M_next) 307 __iter->_M_version = _M_version; 308 309 for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2; 310 __iter2 = __iter2->_M_next) 311 __iter2->_M_version = _M_version; 312 } 313 314 void 315 _Safe_sequence_base:: 316 _M_swap(_Safe_sequence_base& __x) noexcept 317 { swap_seq(_M_get_mutex(), *this, __x._M_get_mutex(), __x); } 318 319 __gnu_cxx::__mutex& 320 _Safe_sequence_base:: 321 _M_get_mutex() throw () 322 { return get_safe_base_mutex(this); } 323 324 void 325 _Safe_sequence_base:: 326 _M_attach(_Safe_iterator_base* __it, bool __constant) 327 { 328 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 329 _M_attach_single(__it, __constant); 330 } 331 332 void 333 _Safe_sequence_base:: 334 _M_attach_single(_Safe_iterator_base* __it, bool __constant) throw () 335 { 336 _Safe_iterator_base*& __its = 337 __constant ? _M_const_iterators : _M_iterators; 338 __it->_M_next = __its; 339 if (__it->_M_next) 340 __it->_M_next->_M_prior = __it; 341 __its = __it; 342 } 343 344 void 345 _Safe_sequence_base:: 346 _M_detach(_Safe_iterator_base* __it) 347 { 348 // Remove __it from this sequence's list 349 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 350 _M_detach_single(__it); 351 } 352 353 void 354 _Safe_sequence_base:: 355 _M_detach_single(_Safe_iterator_base* __it) throw () 356 { 357 // Remove __it from this sequence's list 358 __it->_M_unlink(); 359 if (_M_const_iterators == __it) 360 _M_const_iterators = __it->_M_next; 361 if (_M_iterators == __it) 362 _M_iterators = __it->_M_next; 363 } 364 365 void 366 _Safe_iterator_base:: 367 _M_attach(_Safe_sequence_base* __seq, bool __constant) 368 { 369 _M_detach(); 370 371 // Attach to the new sequence (if there is one) 372 if (__seq) 373 { 374 _M_sequence = __seq; 375 _M_version = _M_sequence->_M_version; 376 _M_sequence->_M_attach(this, __constant); 377 } 378 } 379 380 void 381 _Safe_iterator_base:: 382 _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw () 383 { 384 _M_detach_single(); 385 386 // Attach to the new sequence (if there is one) 387 if (__seq) 388 { 389 _M_sequence = __seq; 390 _M_version = _M_sequence->_M_version; 391 _M_sequence->_M_attach_single(this, __constant); 392 } 393 } 394 395 void 396 _Safe_iterator_base:: 397 _M_detach() 398 { 399 // This function can run concurrently with the sequence destructor, 400 // so there is a TOCTTOU race here: the sequence could be destroyed 401 // after we check that _M_sequence is not null. Use the pointer value 402 // to acquire the mutex (rather than via _M_sequence->_M_get_mutex()). 403 // If the sequence destructor runs between loading the pointer and 404 // locking the mutex, it will detach this iterator and set _M_sequence 405 // to null, and then _M_detach_single() will do nothing. 406 if (auto seq = __atomic_load_n(&_M_sequence, __ATOMIC_ACQUIRE)) 407 { 408 __gnu_cxx::__scoped_lock sentry(get_safe_base_mutex(seq)); 409 _M_detach_single(); 410 } 411 } 412 413 void 414 _Safe_iterator_base:: 415 _M_detach_single() throw () 416 { 417 if (_M_sequence) 418 { 419 _M_sequence->_M_detach_single(this); 420 _M_reset(); 421 } 422 } 423 424 void 425 _Safe_iterator_base:: 426 _M_reset() throw () 427 { 428 __atomic_store_n(&_M_sequence, (_Safe_sequence_base*)0, __ATOMIC_RELEASE); 429 _M_version = 0; 430 _M_prior = 0; 431 _M_next = 0; 432 } 433 434 bool 435 _Safe_iterator_base:: 436 _M_singular() const throw () 437 { return !_M_sequence || _M_version != _M_sequence->_M_version; } 438 439 bool 440 _Safe_iterator_base:: 441 _M_can_compare(const _Safe_iterator_base& __x) const throw () 442 { return _M_sequence == __x._M_sequence; } 443 444 __gnu_cxx::__mutex& 445 _Safe_iterator_base:: 446 _M_get_mutex() throw () 447 { return _M_sequence->_M_get_mutex(); } 448 449 _Safe_unordered_container_base* 450 _Safe_local_iterator_base:: 451 _M_get_container() const noexcept 452 { return static_cast<_Safe_unordered_container_base*>(_M_sequence); } 453 454 void 455 _Safe_local_iterator_base:: 456 _M_attach(_Safe_sequence_base* __cont, bool __constant) 457 { 458 _M_detach(); 459 460 // Attach to the new container (if there is one) 461 if (__cont) 462 { 463 _M_sequence = __cont; 464 _M_version = _M_sequence->_M_version; 465 _M_get_container()->_M_attach_local(this, __constant); 466 } 467 } 468 469 void 470 _Safe_local_iterator_base:: 471 _M_attach_single(_Safe_sequence_base* __cont, bool __constant) throw () 472 { 473 _M_detach_single(); 474 475 // Attach to the new container (if there is one) 476 if (__cont) 477 { 478 _M_sequence = __cont; 479 _M_version = _M_sequence->_M_version; 480 _M_get_container()->_M_attach_local_single(this, __constant); 481 } 482 } 483 484 void 485 _Safe_local_iterator_base:: 486 _M_detach() 487 { 488 if (auto seq = __atomic_load_n(&_M_sequence, __ATOMIC_ACQUIRE)) 489 { 490 __gnu_cxx::__scoped_lock sentry(get_safe_base_mutex(seq)); 491 _M_detach_single(); 492 } 493 } 494 495 void 496 _Safe_local_iterator_base:: 497 _M_detach_single() throw () 498 { 499 if (_M_sequence) 500 { 501 _M_get_container()->_M_detach_local_single(this); 502 _M_reset(); 503 } 504 } 505 506 void 507 _Safe_unordered_container_base:: 508 _M_detach_all() 509 { 510 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 511 detach_all(_M_iterators); 512 _M_iterators = 0; 513 514 detach_all(_M_const_iterators); 515 _M_const_iterators = 0; 516 517 detach_all(_M_local_iterators); 518 _M_local_iterators = 0; 519 520 detach_all(_M_const_local_iterators); 521 _M_const_local_iterators = 0; 522 } 523 524 void 525 _Safe_unordered_container_base:: 526 _M_swap(_Safe_unordered_container_base& __x) noexcept 527 { swap_ucont(_M_get_mutex(), *this, __x._M_get_mutex(), __x); } 528 529 void 530 _Safe_unordered_container_base:: 531 _M_attach_local(_Safe_iterator_base* __it, bool __constant) 532 { 533 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 534 _M_attach_local_single(__it, __constant); 535 } 536 537 void 538 _Safe_unordered_container_base:: 539 _M_attach_local_single(_Safe_iterator_base* __it, bool __constant) throw () 540 { 541 _Safe_iterator_base*& __its = 542 __constant ? _M_const_local_iterators : _M_local_iterators; 543 __it->_M_next = __its; 544 if (__it->_M_next) 545 __it->_M_next->_M_prior = __it; 546 __its = __it; 547 } 548 549 void 550 _Safe_unordered_container_base:: 551 _M_detach_local(_Safe_iterator_base* __it) 552 { 553 // Remove __it from this container's list 554 __gnu_cxx::__scoped_lock sentry(_M_get_mutex()); 555 _M_detach_local_single(__it); 556 } 557 558 void 559 _Safe_unordered_container_base:: 560 _M_detach_local_single(_Safe_iterator_base* __it) throw () 561 { 562 // Remove __it from this container's list 563 __it->_M_unlink(); 564 if (_M_const_local_iterators == __it) 565 _M_const_local_iterators = __it->_M_next; 566 if (_M_local_iterators == __it) 567 _M_local_iterators = __it->_M_next; 568 } 569 } 570 571 namespace 572 { 573 using _Error_formatter = __gnu_debug::_Error_formatter; 574 using _Parameter = __gnu_debug::_Error_formatter::_Parameter; 575 576 void 577 get_max_length(std::size_t& max_length) 578 { 579 const char* nptr = std::getenv("GLIBCXX_DEBUG_MESSAGE_LENGTH"); 580 if (nptr) 581 { 582 char* endptr; 583 const unsigned long ret = std::strtoul(nptr, &endptr, 0); 584 if (*nptr != '\0' && *endptr == '\0') 585 max_length = ret; 586 } 587 } 588 589 struct PrintContext 590 { 591 PrintContext() 592 : _M_max_length(78), _M_column(1), _M_first_line(true), _M_wordwrap(false) 593 { get_max_length(_M_max_length); } 594 595 static constexpr int _S_indent = 4; 596 std::size_t _M_max_length; 597 std::size_t _M_column; 598 bool _M_first_line; 599 bool _M_wordwrap; 600 }; 601 602 using _Print_func_t = void (PrintContext&, const char*, ptrdiff_t); 603 604 template<size_t Length> 605 void 606 print_literal(PrintContext& ctx, const char(&word)[Length]) 607 { print_word(ctx, word, Length - 1); } 608 609 void 610 print_raw(PrintContext& ctx, const char* str, ptrdiff_t nbc = -1) 611 { 612 if (nbc >= 0) 613 ctx._M_column += fprintf(stderr, "%.*s", (int)nbc, str); 614 else 615 ctx._M_column += fprintf(stderr, "%s", str); 616 } 617 618 void 619 print_word(PrintContext& ctx, const char* word, ptrdiff_t nbc = -1) 620 { 621 size_t length = nbc >= 0 ? nbc : __builtin_strlen(word); 622 if (length == 0) 623 return; 624 625 // First consider '\n' at the beginning because it impacts the column. 626 if (word[0] == '\n') 627 { 628 fprintf(stderr, "\n"); 629 ctx._M_column = 1; 630 ++word; 631 --length; 632 633 if (length == 0) 634 return; 635 } 636 637 size_t visual_length 638 = isspace((unsigned char)word[length - 1]) ? length - 1 : length; 639 if (visual_length == 0 640 || !ctx._M_wordwrap 641 || (ctx._M_column + visual_length < ctx._M_max_length) 642 || (visual_length >= ctx._M_max_length && ctx._M_column == 1)) 643 { 644 // If this isn't the first line, indent 645 if (ctx._M_column == 1 && !ctx._M_first_line) 646 { 647 const char spacing[PrintContext::_S_indent + 1] = " "; 648 print_raw(ctx, spacing, PrintContext::_S_indent); 649 } 650 651 int written = fprintf(stderr, "%.*s", (int)length, word); 652 653 if (word[length - 1] == '\n') 654 { 655 ctx._M_first_line = false; 656 ctx._M_column = 1; 657 } 658 else 659 ctx._M_column += written; 660 } 661 else 662 { 663 print_literal(ctx, "\n"); 664 print_word(ctx, word, nbc); 665 } 666 } 667 668 void 669 pretty_print(PrintContext& ctx, const char* str, _Print_func_t print_func) 670 { 671 const char cxx1998[] = "cxx1998::"; 672 for (;;) 673 { 674 if (auto pos = strstr(str, "__")) 675 { 676 if (pos != str) 677 print_func(ctx, str, pos - str); 678 679 pos += 2; // advance past "__" 680 if (memcmp(pos, cxx1998, 9) == 0) 681 pos += 9; // advance part "cxx1998::" 682 683 str = pos; 684 } 685 else 686 { 687 print_func(ctx, str, -1); 688 break; 689 } 690 } 691 } 692 693 template<size_t Length> 694 void 695 print_type_info(PrintContext& ctx, 696 const type_info* info, 697 const char(&unknown_name)[Length]) 698 { 699 if (!info) 700 print_literal(ctx, unknown_name); 701 else 702 { 703 int status; 704 char* demangled_name = 705 __cxxabiv1::__cxa_demangle(info->name(), NULL, NULL, &status); 706 if (status == 0) 707 pretty_print(ctx, demangled_name, &print_word); 708 else 709 print_word(ctx, info->name()); 710 free(demangled_name); 711 } 712 } 713 714 void 715 print_address(PrintContext& ctx, const char* fmt, const void* address) 716 { 717 char buf[128]; 718 int written = __builtin_sprintf(buf, fmt, address); 719 print_word(ctx, buf, written); 720 } 721 722 void 723 print_address(PrintContext& ctx, const void* address) 724 { print_address(ctx, "%p", address); } 725 726 void 727 print_integer(PrintContext& ctx, long integer) 728 { 729 char buf[64]; 730 int written = __builtin_sprintf(buf, "%ld", integer); 731 print_word(ctx, buf, written); 732 } 733 734 void 735 print_named_name(PrintContext& ctx, const _Parameter::_Named& named) 736 { 737 assert(named._M_name); 738 pretty_print(ctx, named._M_name, print_word); 739 } 740 741 template<typename _Iterator> 742 void 743 print_iterator_constness(PrintContext& ctx, const _Iterator& iterator) 744 { 745 static const char* 746 constness_names[_Error_formatter::__last_constness] = 747 { 748 "<unknown constness>", 749 "constant", 750 "mutable" 751 }; 752 print_word(ctx, constness_names[iterator._M_constness]); 753 } 754 755 template<typename _Iterator> 756 void 757 print_iterator_state(PrintContext& ctx, const _Iterator& iterator) 758 { 759 static const char* 760 state_names[_Error_formatter::__last_state] = 761 { 762 "<unknown state>", 763 "singular", 764 "dereferenceable (start-of-sequence)", 765 "dereferenceable", 766 "past-the-end", 767 "before-begin", 768 "dereferenceable (start-of-reverse-sequence)", 769 "dereferenceable (reverse)", 770 "past-the-reverse-end" 771 }; 772 print_word(ctx, state_names[iterator._M_state]); 773 } 774 775 template<typename _Iterator> 776 void 777 print_iterator_seq_type(PrintContext& ctx, const _Iterator& iterator) 778 { print_type_info(ctx, iterator._M_seq_type, "<unknown seq_type>"); } 779 780 bool 781 print_named_field(PrintContext& ctx, 782 const char* fname, const _Parameter::_Named& named) 783 { 784 if (__builtin_strcmp(fname, "name") == 0) 785 print_named_name(ctx, named); 786 else 787 return false; 788 789 return true; 790 } 791 792 bool 793 print_type_field(PrintContext& ctx, 794 const char* fname, const _Parameter::_Type& type) 795 { 796 if (print_named_field(ctx, fname, type)) 797 { } 798 else if (__builtin_strcmp(fname, "type") == 0) 799 print_type_info(ctx, type._M_type, "<unknown type>"); 800 else 801 return false; 802 803 return true; 804 } 805 806 bool 807 print_instance_field(PrintContext& ctx, 808 const char* fname, const _Parameter::_Instance& inst) 809 { 810 if (print_type_field(ctx, fname, inst)) 811 { } 812 else if (__builtin_strcmp(fname, "address") == 0) 813 print_address(ctx, inst._M_address); 814 else 815 return false; 816 817 return true; 818 } 819 820 template<typename _Iterator> 821 bool 822 print_iterator_field(PrintContext& ctx, 823 const char* fname, const _Iterator& iterator) 824 { 825 if (print_instance_field(ctx, fname, iterator)) 826 { } 827 else if (__builtin_strcmp(fname, "constness") == 0) 828 print_iterator_constness(ctx, iterator); 829 else if (__builtin_strcmp(fname, "state") == 0) 830 print_iterator_state(ctx, iterator); 831 else if (__builtin_strcmp(fname, "sequence") == 0) 832 { 833 assert(iterator._M_sequence); 834 print_address(ctx, iterator._M_sequence); 835 } 836 else if (__builtin_strcmp(fname, "seq_type") == 0) 837 print_iterator_seq_type(ctx, iterator); 838 else 839 return false; 840 841 return true; 842 } 843 844 void 845 print_field(PrintContext& ctx, const _Parameter& param, const char* fname) 846 { 847 assert(param._M_kind != _Parameter::__unused_param); 848 849 const auto& variant = param._M_variant; 850 switch (param._M_kind) 851 { 852 case _Parameter::__iterator: 853 if (!print_iterator_field(ctx, fname, variant._M_iterator)) 854 assert(false); 855 break; 856 857 case _Parameter::__sequence: 858 if (!print_instance_field(ctx, fname, variant._M_sequence)) 859 assert(false); 860 break; 861 862 case _Parameter::__integer: 863 if (!print_named_field(ctx, fname, variant._M_integer)) 864 assert(false); 865 break; 866 867 case _Parameter::__string: 868 if (!print_named_field(ctx, fname, variant._M_string)) 869 assert(false); 870 break; 871 872 case _Parameter::__instance: 873 if (!print_instance_field(ctx, fname, variant._M_instance)) 874 assert(false); 875 break; 876 877 case _Parameter::__iterator_value_type: 878 if (!print_type_field(ctx, fname, variant._M_iterator_value_type)) 879 assert(false); 880 break; 881 882 default: 883 assert(false); 884 break; 885 } 886 } 887 888 void 889 print_quoted_named_name(PrintContext& ctx, const _Parameter::_Named& named) 890 { 891 if (named._M_name) 892 { 893 print_literal(ctx, "\""); 894 print_named_name(ctx, named); 895 print_literal(ctx, "\" "); 896 } 897 } 898 899 void 900 print_type_type(PrintContext& ctx, const _Parameter::_Type& type, 901 bool close_desc = true) 902 { 903 if (type._M_type) 904 { 905 print_literal(ctx, " type = "); 906 print_type_info(ctx, type._M_type, "<unknown type>"); 907 if (close_desc) 908 print_literal(ctx, ";\n"); 909 } 910 } 911 912 void 913 print_type(PrintContext& ctx, const _Parameter::_Type& type) 914 { 915 print_quoted_named_name(ctx, type); 916 print_literal(ctx, " {\n"); 917 print_type_type(ctx, type); 918 print_literal(ctx, "}\n"); 919 } 920 921 void 922 print_instance(PrintContext& ctx, const _Parameter::_Instance& inst, 923 bool close_desc = true) 924 { 925 print_quoted_named_name(ctx, inst); 926 print_address(ctx, "@ %p {\n", inst._M_address); 927 print_type_type(ctx, inst, close_desc); 928 929 if (close_desc) 930 print_literal(ctx, "}\n"); 931 } 932 933 void 934 print_description(PrintContext& ctx, const _Parameter& param) 935 { 936 const auto& variant = param._M_variant; 937 switch (param._M_kind) 938 { 939 case _Parameter::__iterator: 940 { 941 const auto& ite = variant._M_iterator; 942 943 print_literal(ctx, "iterator "); 944 print_instance(ctx, ite, false); 945 946 if (ite._M_type) 947 { 948 if (ite._M_constness != _Error_formatter::__unknown_constness) 949 { 950 print_literal(ctx, " ("); 951 print_iterator_constness(ctx, ite); 952 print_literal(ctx, " iterator)"); 953 } 954 955 print_literal(ctx, ";\n"); 956 } 957 958 if (ite._M_state != _Error_formatter::__unknown_state) 959 { 960 print_literal(ctx, " state = "); 961 print_iterator_state(ctx, ite); 962 print_literal(ctx, ";\n"); 963 } 964 965 if (ite._M_sequence) 966 { 967 print_literal(ctx, " references sequence "); 968 if (ite._M_seq_type) 969 { 970 print_literal(ctx, "with type '"); 971 print_iterator_seq_type(ctx, ite); 972 print_literal(ctx, "' "); 973 } 974 975 print_address(ctx, "@ %p\n", ite._M_sequence); 976 } 977 978 print_literal(ctx, "}\n"); 979 } 980 break; 981 982 case _Parameter::__sequence: 983 print_literal(ctx, "sequence "); 984 print_instance(ctx, variant._M_sequence); 985 break; 986 987 case _Parameter::__instance: 988 print_literal(ctx, "instance "); 989 print_instance(ctx, variant._M_instance); 990 break; 991 992 case _Parameter::__iterator_value_type: 993 print_literal(ctx, "iterator::value_type "); 994 print_type(ctx, variant._M_iterator_value_type); 995 break; 996 997 default: 998 break; 999 } 1000 } 1001 1002 void 1003 print_string(PrintContext& ctx, const char* str, ptrdiff_t nbc, 1004 const _Parameter* parameters, std::size_t num_parameters) 1005 { 1006 const char* start = str; 1007 const char* end = nbc >= 0 ? start + nbc : nullptr; 1008 1009 while ((end && str != end) || (!end && *str)) 1010 { 1011 if (isspace((unsigned char)*str)) 1012 { 1013 ++str; 1014 print_word(ctx, start, str - start); 1015 start = str; 1016 continue; 1017 } 1018 1019 if (!parameters || *str != '%') 1020 { 1021 // Normal char or no parameter to look for. 1022 ++str; 1023 continue; 1024 } 1025 1026 if (*++str == '%') 1027 { 1028 // Escaped '%' 1029 print_word(ctx, start, str - start); 1030 ++str; 1031 start = str; 1032 continue; 1033 } 1034 1035 // We are on a parameter property reference, we need to flush buffer 1036 // first. 1037 if (str != start) 1038 { 1039 // Avoid printing the '%'. 1040 if (str - start > 1) 1041 print_word(ctx, start, str - start - 1); 1042 start = str; 1043 } 1044 1045 // Get the parameter number 1046 assert(*str >= '1' && *str <= '9'); 1047 size_t param_index = *str - '0' - 1; 1048 assert(param_index < num_parameters); 1049 const auto& param = parameters[param_index]; 1050 1051 // '.' separates the parameter number from the field 1052 // name, if there is one. 1053 ++str; 1054 if (*str != '.') 1055 { 1056 assert(*str == ';'); 1057 ++str; 1058 if (param._M_kind == _Parameter::__integer) 1059 print_integer(ctx, param._M_variant._M_integer._M_value); 1060 else if (param._M_kind == _Parameter::__string) 1061 print_string(ctx, param._M_variant._M_string._M_value, -1, 1062 parameters, num_parameters); 1063 start = str; 1064 continue; 1065 } 1066 1067 // Extract the field name we want 1068 const int max_field_len = 16; 1069 char field[max_field_len]; 1070 int field_idx = 0; 1071 ++str; 1072 while (*str != ';') 1073 { 1074 assert(*str); 1075 assert(field_idx < max_field_len - 1); 1076 field[field_idx++] = *str++; 1077 } 1078 ++str; 1079 field[field_idx] = '\0'; 1080 1081 print_field(ctx, param, field); 1082 start = str; 1083 } 1084 1085 // Might need to flush. 1086 if (str != start) 1087 print_word(ctx, start, str - start); 1088 } 1089 1090 void 1091 print_string(PrintContext& ctx, const char* str, ptrdiff_t nbc) 1092 { print_string(ctx, str, nbc, nullptr, 0); } 1093 } 1094 1095 namespace __gnu_debug 1096 { 1097 _Error_formatter& 1098 _Error_formatter::_M_message(_Debug_msg_id __id) const throw () 1099 { 1100 return const_cast<_Error_formatter*>(this) 1101 ->_M_message(_S_debug_messages[__id]); 1102 } 1103 1104 void 1105 _Error_formatter::_M_error() const 1106 { 1107 // Emit file & line number information 1108 bool go_to_next_line = false; 1109 PrintContext ctx; 1110 if (_M_file) 1111 { 1112 print_raw(ctx, _M_file); 1113 print_literal(ctx, ":"); 1114 go_to_next_line = true; 1115 } 1116 1117 if (_M_line > 0) 1118 { 1119 ctx._M_column += fprintf(stderr, "%u", _M_line); 1120 print_literal(ctx, ":"); 1121 go_to_next_line = true; 1122 } 1123 1124 if (go_to_next_line) 1125 print_literal(ctx, "\n"); 1126 1127 if (ctx._M_max_length) 1128 ctx._M_wordwrap = true; 1129 1130 if (_M_function) 1131 { 1132 print_literal(ctx, "In function:\n"); 1133 pretty_print(ctx, _M_function, &print_string); 1134 print_literal(ctx, "\n"); 1135 ctx._M_first_line = true; 1136 print_literal(ctx, "\n"); 1137 } 1138 1139 print_literal(ctx, "Error: "); 1140 1141 // Print the error message 1142 assert(_M_text); 1143 print_string(ctx, _M_text, -1, _M_parameters, _M_num_parameters); 1144 print_literal(ctx, ".\n"); 1145 1146 // Emit descriptions of the objects involved in the operation 1147 ctx._M_first_line = true; 1148 ctx._M_wordwrap = false; 1149 bool has_header = false; 1150 for (unsigned int i = 0; i < _M_num_parameters; ++i) 1151 { 1152 switch (_M_parameters[i]._M_kind) 1153 { 1154 case _Parameter::__iterator: 1155 case _Parameter::__sequence: 1156 case _Parameter::__instance: 1157 case _Parameter::__iterator_value_type: 1158 if (!has_header) 1159 { 1160 print_literal(ctx, "\nObjects involved in the operation:\n"); 1161 has_header = true; 1162 } 1163 print_description(ctx, _M_parameters[i]); 1164 break; 1165 1166 default: 1167 break; 1168 } 1169 } 1170 1171 abort(); 1172 } 1173 1174 #if !_GLIBCXX_INLINE_VERSION 1175 // Deprecated methods kept for backward compatibility. 1176 void 1177 _Error_formatter::_Parameter::_M_print_field( 1178 const _Error_formatter*, const char*) const 1179 { } 1180 1181 void 1182 _Error_formatter::_Parameter::_M_print_description(const _Error_formatter*) const 1183 { } 1184 1185 template<typename _Tp> 1186 void 1187 _Error_formatter::_M_format_word(char*, int, const char*, _Tp) 1188 const throw () 1189 { } 1190 1191 void 1192 _Error_formatter::_M_print_word(const char*) const 1193 { } 1194 1195 void 1196 _Error_formatter::_M_print_string(const char*) const 1197 { } 1198 1199 void 1200 _Error_formatter::_M_get_max_length() const throw () 1201 { } 1202 1203 // Instantiations. 1204 template 1205 void 1206 _Error_formatter::_M_format_word(char*, int, const char*, 1207 const void*) const; 1208 1209 template 1210 void 1211 _Error_formatter::_M_format_word(char*, int, const char*, long) const; 1212 1213 template 1214 void 1215 _Error_formatter::_M_format_word(char*, int, const char*, 1216 std::size_t) const; 1217 1218 template 1219 void 1220 _Error_formatter::_M_format_word(char*, int, const char*, 1221 const char*) const; 1222 #endif 1223 1224 } // namespace __gnu_debug 1225