1 /* 2 * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "jvm.h" 27 #include "classfile/systemDictionary.hpp" 28 #include "code/codeCache.hpp" 29 #include "code/icBuffer.hpp" 30 #include "code/nmethod.hpp" 31 #include "code/vtableStubs.hpp" 32 #include "compiler/compileBroker.hpp" 33 #include "compiler/disassembler.hpp" 34 #include "gc/shared/collectedHeap.hpp" 35 #include "interpreter/bytecodeHistogram.hpp" 36 #include "interpreter/interpreter.hpp" 37 #include "memory/resourceArea.hpp" 38 #include "memory/universe.hpp" 39 #include "oops/oop.inline.hpp" 40 #include "runtime/arguments.hpp" 41 #include "runtime/atomic.hpp" 42 #include "runtime/flags/flagSetting.hpp" 43 #include "runtime/frame.inline.hpp" 44 #include "runtime/handles.inline.hpp" 45 #include "runtime/java.hpp" 46 #include "runtime/os.hpp" 47 #include "runtime/sharedRuntime.hpp" 48 #include "runtime/stubCodeGenerator.hpp" 49 #include "runtime/stubRoutines.hpp" 50 #include "runtime/thread.inline.hpp" 51 #include "runtime/vframe.hpp" 52 #include "runtime/vm_version.hpp" 53 #include "services/heapDumper.hpp" 54 #include "utilities/defaultStream.hpp" 55 #include "utilities/events.hpp" 56 #include "utilities/formatBuffer.hpp" 57 #include "utilities/globalDefinitions.hpp" 58 #include "utilities/macros.hpp" 59 #include "utilities/vmError.hpp" 60 61 #include <stdio.h> 62 63 // Support for showing register content on asserts/guarantees. 64 #ifdef CAN_SHOW_REGISTERS_ON_ASSERT 65 static char g_dummy; 66 char* g_assert_poison = &g_dummy; 67 static intx g_asserting_thread = 0; 68 static void* g_assertion_context = NULL; 69 #endif // CAN_SHOW_REGISTERS_ON_ASSERT 70 71 #ifndef ASSERT 72 # ifdef _DEBUG 73 // NOTE: don't turn the lines below into a comment -- if you're getting 74 // a compile error here, change the settings to define ASSERT 75 ASSERT should be defined when _DEBUG is defined. It is not intended to be used for debugging 76 functions that do not slow down the system too much and thus can be left in optimized code. 77 On the other hand, the code should not be included in a production version. 78 # endif // _DEBUG 79 #endif // ASSERT 80 81 82 #ifdef _DEBUG 83 # ifndef ASSERT 84 configuration error: ASSERT must be defined in debug version 85 # endif // ASSERT 86 #endif // _DEBUG 87 88 89 #ifdef PRODUCT 90 # if -defined _DEBUG || -defined ASSERT 91 configuration error: ASSERT et al. must not be defined in PRODUCT version 92 # endif 93 #endif // PRODUCT 94 95 ATTRIBUTE_PRINTF(1, 2) 96 void warning(const char* format, ...) { 97 if (PrintWarnings) { 98 FILE* const err = defaultStream::error_stream(); 99 jio_fprintf(err, "%s warning: ", VM_Version::vm_name()); 100 va_list ap; 101 va_start(ap, format); 102 vfprintf(err, format, ap); 103 va_end(ap); 104 fputc('\n', err); 105 } 106 if (BreakAtWarning) BREAKPOINT; 107 } 108 109 #ifndef PRODUCT 110 111 #define is_token_break(ch) (isspace(ch) || (ch) == ',') 112 113 static const char* last_file_name = NULL; 114 static int last_line_no = -1; 115 116 // assert/guarantee/... may happen very early during VM initialization. 117 // Don't rely on anything that is initialized by Threads::create_vm(). For 118 // example, don't use tty. 119 bool error_is_suppressed(const char* file_name, int line_no) { 120 // The following 1-element cache requires that passed-in 121 // file names are always only constant literals. 122 if (file_name == last_file_name && line_no == last_line_no) return true; 123 124 int file_name_len = (int)strlen(file_name); 125 char separator = os::file_separator()[0]; 126 const char* base_name = strrchr(file_name, separator); 127 if (base_name == NULL) 128 base_name = file_name; 129 130 // scan the SuppressErrorAt option 131 const char* cp = SuppressErrorAt; 132 for (;;) { 133 const char* sfile; 134 int sfile_len; 135 int sline; 136 bool noisy; 137 while ((*cp) != '\0' && is_token_break(*cp)) cp++; 138 if ((*cp) == '\0') break; 139 sfile = cp; 140 while ((*cp) != '\0' && !is_token_break(*cp) && (*cp) != ':') cp++; 141 sfile_len = cp - sfile; 142 if ((*cp) == ':') cp++; 143 sline = 0; 144 while ((*cp) != '\0' && isdigit(*cp)) { 145 sline *= 10; 146 sline += (*cp) - '0'; 147 cp++; 148 } 149 // "file:line!" means the assert suppression is not silent 150 noisy = ((*cp) == '!'); 151 while ((*cp) != '\0' && !is_token_break(*cp)) cp++; 152 // match the line 153 if (sline != 0) { 154 if (sline != line_no) continue; 155 } 156 // match the file 157 if (sfile_len > 0) { 158 const char* look = file_name; 159 const char* look_max = file_name + file_name_len - sfile_len; 160 const char* foundp; 161 bool match = false; 162 while (!match 163 && (foundp = strchr(look, sfile[0])) != NULL 164 && foundp <= look_max) { 165 match = true; 166 for (int i = 1; i < sfile_len; i++) { 167 if (sfile[i] != foundp[i]) { 168 match = false; 169 break; 170 } 171 } 172 look = foundp + 1; 173 } 174 if (!match) continue; 175 } 176 // got a match! 177 if (noisy) { 178 fdStream out(defaultStream::output_fd()); 179 out.print_raw("[error suppressed at "); 180 out.print_raw(base_name); 181 char buf[16]; 182 jio_snprintf(buf, sizeof(buf), ":%d]", line_no); 183 out.print_raw_cr(buf); 184 } else { 185 // update 1-element cache for fast silent matches 186 last_file_name = file_name; 187 last_line_no = line_no; 188 } 189 return true; 190 } 191 192 if (!VMError::is_error_reported() && !SuppressFatalErrorMessage) { 193 // print a friendly hint: 194 fdStream out(defaultStream::output_fd()); 195 out.print_raw_cr("# To suppress the following error report, specify this argument"); 196 out.print_raw ("# after -XX: or in .hotspotrc: SuppressErrorAt="); 197 out.print_raw (base_name); 198 char buf[16]; 199 jio_snprintf(buf, sizeof(buf), ":%d", line_no); 200 out.print_raw_cr(buf); 201 } 202 return false; 203 } 204 205 #undef is_token_break 206 207 #else 208 209 // Place-holder for non-existent suppression check: 210 #define error_is_suppressed(file_name, line_no) (false) 211 212 #endif // !PRODUCT 213 214 void report_vm_error(const char* file, int line, const char* error_msg) 215 { 216 report_vm_error(file, line, error_msg, "%s", ""); 217 } 218 219 void report_vm_error(const char* file, int line, const char* error_msg, const char* detail_fmt, ...) 220 { 221 if (Debugging || error_is_suppressed(file, line)) return; 222 va_list detail_args; 223 va_start(detail_args, detail_fmt); 224 void* context = NULL; 225 #ifdef CAN_SHOW_REGISTERS_ON_ASSERT 226 if (g_assertion_context != NULL && os::current_thread_id() == g_asserting_thread) { 227 context = g_assertion_context; 228 } 229 #endif // CAN_SHOW_REGISTERS_ON_ASSERT 230 VMError::report_and_die(Thread::current_or_null(), context, file, line, error_msg, detail_fmt, detail_args); 231 va_end(detail_args); 232 } 233 234 void report_vm_status_error(const char* file, int line, const char* error_msg, 235 int status, const char* detail) { 236 report_vm_error(file, line, error_msg, "error %s(%d), %s", os::errno_name(status), status, detail); 237 } 238 239 void report_fatal(const char* file, int line, const char* detail_fmt, ...) 240 { 241 if (Debugging || error_is_suppressed(file, line)) return; 242 va_list detail_args; 243 va_start(detail_args, detail_fmt); 244 void* context = NULL; 245 #ifdef CAN_SHOW_REGISTERS_ON_ASSERT 246 if (g_assertion_context != NULL && os::current_thread_id() == g_asserting_thread) { 247 context = g_assertion_context; 248 } 249 #endif // CAN_SHOW_REGISTERS_ON_ASSERT 250 VMError::report_and_die(Thread::current_or_null(), context, file, line, "fatal error", detail_fmt, detail_args); 251 va_end(detail_args); 252 } 253 254 void report_vm_out_of_memory(const char* file, int line, size_t size, 255 VMErrorType vm_err_type, const char* detail_fmt, ...) { 256 if (Debugging) return; 257 va_list detail_args; 258 va_start(detail_args, detail_fmt); 259 VMError::report_and_die(Thread::current_or_null(), file, line, size, vm_err_type, detail_fmt, detail_args); 260 va_end(detail_args); 261 262 // The UseOSErrorReporting option in report_and_die() may allow a return 263 // to here. If so then we'll have to figure out how to handle it. 264 guarantee(false, "report_and_die() should not return here"); 265 } 266 267 void report_should_not_call(const char* file, int line) { 268 report_vm_error(file, line, "ShouldNotCall()"); 269 } 270 271 void report_should_not_reach_here(const char* file, int line) { 272 report_vm_error(file, line, "ShouldNotReachHere()"); 273 } 274 275 void report_unimplemented(const char* file, int line) { 276 report_vm_error(file, line, "Unimplemented()"); 277 } 278 279 #ifdef ASSERT 280 bool is_executing_unit_tests() { 281 return ExecutingUnitTests; 282 } 283 284 void report_assert_msg(const char* msg, ...) { 285 va_list ap; 286 va_start(ap, msg); 287 288 fprintf(stderr, "assert failed: %s\n", err_msg(FormatBufferDummy(), msg, ap).buffer()); 289 290 va_end(ap); 291 } 292 #endif // ASSERT 293 294 void report_untested(const char* file, int line, const char* message) { 295 #ifndef PRODUCT 296 warning("Untested: %s in %s: %d\n", message, file, line); 297 #endif // !PRODUCT 298 } 299 300 void report_java_out_of_memory(const char* message) { 301 static int out_of_memory_reported = 0; 302 303 // A number of threads may attempt to report OutOfMemoryError at around the 304 // same time. To avoid dumping the heap or executing the data collection 305 // commands multiple times we just do it once when the first threads reports 306 // the error. 307 if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) { 308 // create heap dump before OnOutOfMemoryError commands are executed 309 if (HeapDumpOnOutOfMemoryError) { 310 tty->print_cr("java.lang.OutOfMemoryError: %s", message); 311 HeapDumper::dump_heap_from_oome(); 312 } 313 314 if (OnOutOfMemoryError && OnOutOfMemoryError[0]) { 315 VMError::report_java_out_of_memory(message); 316 } 317 318 if (CrashOnOutOfMemoryError) { 319 tty->print_cr("Aborting due to java.lang.OutOfMemoryError: %s", message); 320 fatal("OutOfMemory encountered: %s", message); 321 } 322 323 if (ExitOnOutOfMemoryError) { 324 tty->print_cr("Terminating due to java.lang.OutOfMemoryError: %s", message); 325 os::exit(3); 326 } 327 } 328 } 329 330 // ------ helper functions for debugging go here ------------ 331 332 // All debug entries should be wrapped with a stack allocated 333 // Command object. It makes sure a resource mark is set and 334 // flushes the logfile to prevent file sharing problems. 335 336 class Command : public StackObj { 337 private: 338 ResourceMark rm; 339 ResetNoHandleMark rnhm; 340 HandleMark hm; 341 bool debug_save; 342 public: 343 static int level; 344 Command(const char* str) { 345 debug_save = Debugging; 346 Debugging = true; 347 if (level++ > 0) return; 348 tty->cr(); 349 tty->print_cr("\"Executing %s\"", str); 350 } 351 352 ~Command() { 353 tty->flush(); 354 Debugging = debug_save; 355 level--; 356 } 357 }; 358 359 int Command::level = 0; 360 361 #ifndef PRODUCT 362 363 extern "C" void blob(CodeBlob* cb) { 364 Command c("blob"); 365 cb->print(); 366 } 367 368 369 extern "C" void dump_vtable(address p) { 370 Command c("dump_vtable"); 371 Klass* k = (Klass*)p; 372 k->vtable().print(); 373 } 374 375 376 extern "C" void nm(intptr_t p) { 377 // Actually we look through all CodeBlobs (the nm name has been kept for backwards compatability) 378 Command c("nm"); 379 CodeBlob* cb = CodeCache::find_blob((address)p); 380 if (cb == NULL) { 381 tty->print_cr("NULL"); 382 } else { 383 cb->print(); 384 } 385 } 386 387 388 extern "C" void disnm(intptr_t p) { 389 Command c("disnm"); 390 CodeBlob* cb = CodeCache::find_blob((address) p); 391 if (cb != NULL) { 392 nmethod* nm = cb->as_nmethod_or_null(); 393 if (nm != NULL) { 394 nm->print(); 395 } else { 396 cb->print(); 397 } 398 Disassembler::decode(cb); 399 } 400 } 401 402 403 extern "C" void printnm(intptr_t p) { 404 char buffer[256]; 405 sprintf(buffer, "printnm: " INTPTR_FORMAT, p); 406 Command c(buffer); 407 CodeBlob* cb = CodeCache::find_blob((address) p); 408 if (cb->is_nmethod()) { 409 nmethod* nm = (nmethod*)cb; 410 nm->print_nmethod(true); 411 } 412 } 413 414 415 extern "C" void universe() { 416 Command c("universe"); 417 Universe::print_on(tty); 418 } 419 420 421 extern "C" void verify() { 422 // try to run a verify on the entire system 423 // note: this may not be safe if we're not at a safepoint; for debugging, 424 // this manipulates the safepoint settings to avoid assertion failures 425 Command c("universe verify"); 426 bool safe = SafepointSynchronize::is_at_safepoint(); 427 if (!safe) { 428 tty->print_cr("warning: not at safepoint -- verify may fail"); 429 SafepointSynchronize::set_is_at_safepoint(); 430 } 431 // Ensure Eden top is correct before verification 432 Universe::heap()->prepare_for_verify(); 433 Universe::verify(); 434 if (!safe) SafepointSynchronize::set_is_not_at_safepoint(); 435 } 436 437 438 extern "C" void pp(void* p) { 439 Command c("pp"); 440 FlagSetting fl(PrintVMMessages, true); 441 FlagSetting f2(DisplayVMOutput, true); 442 if (Universe::heap()->is_in(p)) { 443 oop obj = oop(p); 444 obj->print(); 445 } else { 446 tty->print(PTR_FORMAT, p2i(p)); 447 } 448 } 449 450 451 // pv: print vm-printable object 452 extern "C" void pa(intptr_t p) { ((AllocatedObj*) p)->print(); } 453 extern "C" void findpc(intptr_t x); 454 455 #endif // !PRODUCT 456 457 extern "C" void ps() { // print stack 458 if (Thread::current_or_null() == NULL) return; 459 Command c("ps"); 460 461 462 // Prints the stack of the current Java thread 463 JavaThread* p = JavaThread::active(); 464 tty->print(" for thread: "); 465 p->print(); 466 tty->cr(); 467 468 if (p->has_last_Java_frame()) { 469 // If the last_Java_fp is set we are in C land and 470 // can call the standard stack_trace function. 471 #ifdef PRODUCT 472 p->print_stack(); 473 } else { 474 tty->print_cr("Cannot find the last Java frame, printing stack disabled."); 475 #else // !PRODUCT 476 p->trace_stack(); 477 } else { 478 frame f = os::current_frame(); 479 RegisterMap reg_map(p); 480 f = f.sender(®_map); 481 tty->print("(guessing starting frame id=" PTR_FORMAT " based on current fp)\n", p2i(f.id())); 482 p->trace_stack_from(vframe::new_vframe(&f, ®_map, p)); 483 f.pd_ps(); 484 #endif // PRODUCT 485 } 486 487 } 488 489 extern "C" void pfl() { 490 // print frame layout 491 Command c("pfl"); 492 JavaThread* p = JavaThread::active(); 493 tty->print(" for thread: "); 494 p->print(); 495 tty->cr(); 496 if (p->has_last_Java_frame()) { 497 p->print_frame_layout(); 498 } 499 } 500 501 #ifndef PRODUCT 502 503 extern "C" void psf() { // print stack frames 504 { 505 Command c("psf"); 506 JavaThread* p = JavaThread::active(); 507 tty->print(" for thread: "); 508 p->print(); 509 tty->cr(); 510 if (p->has_last_Java_frame()) { 511 p->trace_frames(); 512 } 513 } 514 } 515 516 517 extern "C" void threads() { 518 Command c("threads"); 519 Threads::print(false, true); 520 } 521 522 523 extern "C" void psd() { 524 Command c("psd"); 525 SystemDictionary::print(); 526 } 527 528 #endif // !PRODUCT 529 530 extern "C" void pss() { // print all stacks 531 if (Thread::current_or_null() == NULL) return; 532 Command c("pss"); 533 Threads::print(true, PRODUCT_ONLY(false) NOT_PRODUCT(true)); 534 } 535 536 #ifndef PRODUCT 537 538 extern "C" void debug() { // to set things up for compiler debugging 539 Command c("debug"); 540 WizardMode = true; 541 PrintVMMessages = PrintCompilation = true; 542 PrintInlining = PrintAssembly = true; 543 tty->flush(); 544 } 545 546 547 extern "C" void ndebug() { // undo debug() 548 Command c("ndebug"); 549 PrintCompilation = false; 550 PrintInlining = PrintAssembly = false; 551 tty->flush(); 552 } 553 554 555 extern "C" void flush() { 556 Command c("flush"); 557 tty->flush(); 558 } 559 560 extern "C" void events() { 561 Command c("events"); 562 Events::print(); 563 } 564 565 extern "C" Method* findm(intptr_t pc) { 566 Command c("findm"); 567 nmethod* nm = CodeCache::find_nmethod((address)pc); 568 return (nm == NULL) ? (Method*)NULL : nm->method(); 569 } 570 571 572 extern "C" nmethod* findnm(intptr_t addr) { 573 Command c("findnm"); 574 return CodeCache::find_nmethod((address)addr); 575 } 576 577 // Another interface that isn't ambiguous in dbx. 578 // Can we someday rename the other find to hsfind? 579 extern "C" void hsfind(intptr_t x) { 580 Command c("hsfind"); 581 os::print_location(tty, x, false); 582 } 583 584 585 extern "C" void find(intptr_t x) { 586 Command c("find"); 587 os::print_location(tty, x, false); 588 } 589 590 591 extern "C" void findpc(intptr_t x) { 592 Command c("findpc"); 593 os::print_location(tty, x, true); 594 } 595 596 597 // Need method pointer to find bcp, when not in permgen. 598 extern "C" void findbcp(intptr_t method, intptr_t bcp) { 599 Command c("findbcp"); 600 Method* mh = (Method*)method; 601 if (!mh->is_native()) { 602 tty->print_cr("bci_from(%p) = %d; print_codes():", 603 mh, mh->bci_from(address(bcp))); 604 mh->print_codes_on(tty); 605 } 606 } 607 608 // int versions of all methods to avoid having to type type casts in the debugger 609 610 void pp(intptr_t p) { pp((void*)p); } 611 void pp(oop p) { pp((void*)p); } 612 613 void help() { 614 Command c("help"); 615 tty->print_cr("basic"); 616 tty->print_cr(" pp(void* p) - try to make sense of p"); 617 tty->print_cr(" pv(intptr_t p)- ((PrintableResourceObj*) p)->print()"); 618 tty->print_cr(" ps() - print current thread stack"); 619 tty->print_cr(" pss() - print all thread stacks"); 620 tty->print_cr(" pm(int pc) - print Method* given compiled PC"); 621 tty->print_cr(" findm(intptr_t pc) - finds Method*"); 622 tty->print_cr(" find(intptr_t x) - finds & prints nmethod/stub/bytecode/oop based on pointer into it"); 623 tty->print_cr(" pns(void* sp, void* fp, void* pc) - print native (i.e. mixed) stack trace. E.g."); 624 tty->print_cr(" pns($sp, $rbp, $pc) on Linux/amd64 and Solaris/amd64 or"); 625 tty->print_cr(" pns($sp, $ebp, $pc) on Linux/x86 or"); 626 tty->print_cr(" pns($sp, 0, $pc) on Linux/ppc64 or"); 627 tty->print_cr(" pns($sp + 0x7ff, 0, $pc) on Solaris/SPARC"); 628 tty->print_cr(" - in gdb do 'set overload-resolution off' before calling pns()"); 629 tty->print_cr(" - in dbx do 'frame 1' before calling pns()"); 630 631 tty->print_cr("misc."); 632 tty->print_cr(" flush() - flushes the log file"); 633 tty->print_cr(" events() - dump events from ring buffers"); 634 635 636 tty->print_cr("compiler debugging"); 637 tty->print_cr(" debug() - to set things up for compiler debugging"); 638 tty->print_cr(" ndebug() - undo debug"); 639 } 640 641 extern "C" void pns(void* sp, void* fp, void* pc) { // print native stack 642 Command c("pns"); 643 static char buf[O_BUFLEN]; 644 Thread* t = Thread::current_or_null(); 645 // Call generic frame constructor (certain arguments may be ignored) 646 frame fr(sp, fp, pc); 647 VMError::print_native_stack(tty, fr, t, buf, sizeof(buf)); 648 } 649 650 // 651 // This version of pns() will not work when called from the debugger, but is 652 // useful when called from within hotspot code. The advantages over pns() 653 // are not having to pass in any arguments, and it will work on Windows/x64. 654 // 655 // WARNING: Only intended for use when debugging. Do not leave calls to 656 // pns2() in committed source (product or debug). 657 // 658 extern "C" void pns2() { // print native stack 659 Command c("pns2"); 660 static char buf[O_BUFLEN]; 661 if (os::platform_print_native_stack(tty, NULL, buf, sizeof(buf))) { 662 // We have printed the native stack in platform-specific code, 663 // so nothing else to do in this case. 664 } else { 665 Thread* t = Thread::current_or_null(); 666 frame fr = os::current_frame(); 667 VMError::print_native_stack(tty, fr, t, buf, sizeof(buf)); 668 } 669 } 670 671 #endif // !PRODUCT 672 673 ////////////////////////////////////////////////////////////////////////////// 674 // Test multiple STATIC_ASSERT forms in various scopes. 675 676 #ifndef PRODUCT 677 678 // namespace scope 679 STATIC_ASSERT(true); 680 STATIC_ASSERT(true); 681 STATIC_ASSERT(1 == 1); 682 STATIC_ASSERT(0 == 0); 683 684 void test_multiple_static_assert_forms_in_function_scope() { 685 STATIC_ASSERT(true); 686 STATIC_ASSERT(true); 687 STATIC_ASSERT(0 == 0); 688 STATIC_ASSERT(1 == 1); 689 } 690 691 // class scope 692 struct TestMultipleStaticAssertFormsInClassScope { 693 STATIC_ASSERT(true); 694 STATIC_ASSERT(true); 695 STATIC_ASSERT(0 == 0); 696 STATIC_ASSERT(1 == 1); 697 }; 698 699 #endif // !PRODUCT 700 701 // Support for showing register content on asserts/guarantees. 702 #ifdef CAN_SHOW_REGISTERS_ON_ASSERT 703 704 static ucontext_t g_stored_assertion_context; 705 706 void initialize_assert_poison() { 707 char* page = os::reserve_memory(os::vm_page_size()); 708 if (page) { 709 if (os::commit_memory(page, os::vm_page_size(), false) && 710 os::protect_memory(page, os::vm_page_size(), os::MEM_PROT_NONE)) { 711 g_assert_poison = page; 712 } 713 } 714 } 715 716 static void store_context(const void* context) { 717 memcpy(&g_stored_assertion_context, context, sizeof(ucontext_t)); 718 #if defined(__linux) && defined(PPC64) 719 // on Linux ppc64, ucontext_t contains pointers into itself which have to be patched up 720 // after copying the context (see comment in sys/ucontext.h): 721 *((void**) &g_stored_assertion_context.uc_mcontext.regs) = &(g_stored_assertion_context.uc_mcontext.gp_regs); 722 #endif 723 } 724 725 bool handle_assert_poison_fault(const void* ucVoid, const void* faulting_address) { 726 if (faulting_address == g_assert_poison) { 727 // Disarm poison page. 728 os::protect_memory((char*)g_assert_poison, os::vm_page_size(), os::MEM_PROT_RWX); 729 // Store Context away. 730 if (ucVoid) { 731 const intx my_tid = os::current_thread_id(); 732 if (Atomic::cmpxchg(my_tid, &g_asserting_thread, (intx)0) == 0) { 733 store_context(ucVoid); 734 g_assertion_context = &g_stored_assertion_context; 735 } 736 } 737 return true; 738 } 739 return false; 740 } 741 #endif // CAN_SHOW_REGISTERS_ON_ASSERT 742