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