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