comparison src/share/vm/runtime/os.cpp @ 20318:fa62fb12cdca

6311046: -Xcheck:jni should support checking of GetPrimitiveArrayCritical. Summary: Wrapped memory with standard bounds checking "GuardedMemory". Reviewed-by: zgu, fparain, dcubed
author dsimms
date Thu, 14 Aug 2014 15:16:07 +0200
parents 78bbf4d43a14
children 833b0f92429a
comparison
equal deleted inserted replaced
20317:ee019285a52c 20318:fa62fb12cdca
30 #include "code/icBuffer.hpp" 30 #include "code/icBuffer.hpp"
31 #include "code/vtableStubs.hpp" 31 #include "code/vtableStubs.hpp"
32 #include "gc_implementation/shared/vmGCOperations.hpp" 32 #include "gc_implementation/shared/vmGCOperations.hpp"
33 #include "interpreter/interpreter.hpp" 33 #include "interpreter/interpreter.hpp"
34 #include "memory/allocation.inline.hpp" 34 #include "memory/allocation.inline.hpp"
35 #ifdef ASSERT
36 #include "memory/guardedMemory.hpp"
37 #endif
35 #include "oops/oop.inline.hpp" 38 #include "oops/oop.inline.hpp"
36 #include "prims/jvm.h" 39 #include "prims/jvm.h"
37 #include "prims/jvm_misc.hpp" 40 #include "prims/jvm_misc.hpp"
38 #include "prims/privilegedStack.hpp" 41 #include "prims/privilegedStack.hpp"
39 #include "runtime/arguments.hpp" 42 #include "runtime/arguments.hpp"
522 return dup_str; 525 return dup_str;
523 } 526 }
524 527
525 528
526 529
530 #define paranoid 0 /* only set to 1 if you suspect checking code has bug */
531
527 #ifdef ASSERT 532 #ifdef ASSERT
528 #define space_before (MallocCushion + sizeof(double)) 533 static void verify_memory(void* ptr) {
529 #define space_after MallocCushion 534 GuardedMemory guarded(ptr);
530 #define size_addr_from_base(p) (size_t*)(p + space_before - sizeof(size_t)) 535 if (!guarded.verify_guards()) {
531 #define size_addr_from_obj(p) ((size_t*)p - 1) 536 tty->print_cr("## nof_mallocs = " UINT64_FORMAT ", nof_frees = " UINT64_FORMAT, os::num_mallocs, os::num_frees);
532 // MallocCushion: size of extra cushion allocated around objects with +UseMallocOnly 537 tty->print_cr("## memory stomp:");
533 // NB: cannot be debug variable, because these aren't set from the command line until 538 guarded.print_on(tty);
534 // *after* the first few allocs already happened 539 fatal("memory stomping error");
535 #define MallocCushion 16
536 #else
537 #define space_before 0
538 #define space_after 0
539 #define size_addr_from_base(p) should not use w/o ASSERT
540 #define size_addr_from_obj(p) should not use w/o ASSERT
541 #define MallocCushion 0
542 #endif
543 #define paranoid 0 /* only set to 1 if you suspect checking code has bug */
544
545 #ifdef ASSERT
546 inline size_t get_size(void* obj) {
547 size_t size = *size_addr_from_obj(obj);
548 if (size < 0) {
549 fatal(err_msg("free: size field of object #" PTR_FORMAT " was overwritten ("
550 SIZE_FORMAT ")", obj, size));
551 }
552 return size;
553 }
554
555 u_char* find_cushion_backwards(u_char* start) {
556 u_char* p = start;
557 while (p[ 0] != badResourceValue || p[-1] != badResourceValue ||
558 p[-2] != badResourceValue || p[-3] != badResourceValue) p--;
559 // ok, we have four consecutive marker bytes; find start
560 u_char* q = p - 4;
561 while (*q == badResourceValue) q--;
562 return q + 1;
563 }
564
565 u_char* find_cushion_forwards(u_char* start) {
566 u_char* p = start;
567 while (p[0] != badResourceValue || p[1] != badResourceValue ||
568 p[2] != badResourceValue || p[3] != badResourceValue) p++;
569 // ok, we have four consecutive marker bytes; find end of cushion
570 u_char* q = p + 4;
571 while (*q == badResourceValue) q++;
572 return q - MallocCushion;
573 }
574
575 void print_neighbor_blocks(void* ptr) {
576 // find block allocated before ptr (not entirely crash-proof)
577 if (MallocCushion < 4) {
578 tty->print_cr("### cannot find previous block (MallocCushion < 4)");
579 return;
580 }
581 u_char* start_of_this_block = (u_char*)ptr - space_before;
582 u_char* end_of_prev_block_data = start_of_this_block - space_after -1;
583 // look for cushion in front of prev. block
584 u_char* start_of_prev_block = find_cushion_backwards(end_of_prev_block_data);
585 ptrdiff_t size = *size_addr_from_base(start_of_prev_block);
586 u_char* obj = start_of_prev_block + space_before;
587 if (size <= 0 ) {
588 // start is bad; mayhave been confused by OS data inbetween objects
589 // search one more backwards
590 start_of_prev_block = find_cushion_backwards(start_of_prev_block);
591 size = *size_addr_from_base(start_of_prev_block);
592 obj = start_of_prev_block + space_before;
593 }
594
595 if (start_of_prev_block + space_before + size + space_after == start_of_this_block) {
596 tty->print_cr("### previous object: " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", obj, size);
597 } else {
598 tty->print_cr("### previous object (not sure if correct): " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", obj, size);
599 }
600
601 // now find successor block
602 u_char* start_of_next_block = (u_char*)ptr + *size_addr_from_obj(ptr) + space_after;
603 start_of_next_block = find_cushion_forwards(start_of_next_block);
604 u_char* next_obj = start_of_next_block + space_before;
605 ptrdiff_t next_size = *size_addr_from_base(start_of_next_block);
606 if (start_of_next_block[0] == badResourceValue &&
607 start_of_next_block[1] == badResourceValue &&
608 start_of_next_block[2] == badResourceValue &&
609 start_of_next_block[3] == badResourceValue) {
610 tty->print_cr("### next object: " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", next_obj, next_size);
611 } else {
612 tty->print_cr("### next object (not sure if correct): " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", next_obj, next_size);
613 }
614 }
615
616
617 void report_heap_error(void* memblock, void* bad, const char* where) {
618 tty->print_cr("## nof_mallocs = " UINT64_FORMAT ", nof_frees = " UINT64_FORMAT, os::num_mallocs, os::num_frees);
619 tty->print_cr("## memory stomp: byte at " PTR_FORMAT " %s object " PTR_FORMAT, bad, where, memblock);
620 print_neighbor_blocks(memblock);
621 fatal("memory stomping error");
622 }
623
624 void verify_block(void* memblock) {
625 size_t size = get_size(memblock);
626 if (MallocCushion) {
627 u_char* ptr = (u_char*)memblock - space_before;
628 for (int i = 0; i < MallocCushion; i++) {
629 if (ptr[i] != badResourceValue) {
630 report_heap_error(memblock, ptr+i, "in front of");
631 }
632 }
633 u_char* end = (u_char*)memblock + size + space_after;
634 for (int j = -MallocCushion; j < 0; j++) {
635 if (end[j] != badResourceValue) {
636 report_heap_error(memblock, end+j, "after");
637 }
638 }
639 } 540 }
640 } 541 }
641 #endif 542 #endif
642 543
643 // 544 //
684 // return a valid pointer if size is zero 585 // return a valid pointer if size is zero
685 // if NULL is returned the calling functions assume out of memory. 586 // if NULL is returned the calling functions assume out of memory.
686 size = 1; 587 size = 1;
687 } 588 }
688 589
689 const size_t alloc_size = size + space_before + space_after; 590 #ifndef ASSERT
690 591 const size_t alloc_size = size;
592 #else
593 const size_t alloc_size = GuardedMemory::get_total_size(size);
691 if (size > alloc_size) { // Check for rollover. 594 if (size > alloc_size) { // Check for rollover.
692 return NULL; 595 return NULL;
693 } 596 }
597 #endif
694 598
695 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); 599 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap());
696 600
697 u_char* ptr; 601 u_char* ptr;
698
699 if (MallocMaxTestWords > 0) { 602 if (MallocMaxTestWords > 0) {
700 ptr = testMalloc(alloc_size); 603 ptr = testMalloc(alloc_size);
701 } else { 604 } else {
702 ptr = (u_char*)::malloc(alloc_size); 605 ptr = (u_char*)::malloc(alloc_size);
703 } 606 }
704 607
705 #ifdef ASSERT 608 #ifdef ASSERT
706 if (ptr == NULL) return NULL; 609 if (ptr == NULL) {
707 if (MallocCushion) { 610 return NULL;
708 for (u_char* p = ptr; p < ptr + MallocCushion; p++) *p = (u_char)badResourceValue; 611 }
709 u_char* end = ptr + space_before + size; 612 // Wrap memory with guard
710 for (u_char* pq = ptr+MallocCushion; pq < end; pq++) *pq = (u_char)uninitBlockPad; 613 GuardedMemory guarded(ptr, size);
711 for (u_char* q = end; q < end + MallocCushion; q++) *q = (u_char)badResourceValue; 614 ptr = guarded.get_user_ptr();
712 } 615 #endif
713 // put size just before data 616 if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) {
714 *size_addr_from_base(ptr) = size; 617 tty->print_cr("os::malloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr);
715 #endif
716 u_char* memblock = ptr + space_before;
717 if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) {
718 tty->print_cr("os::malloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, memblock);
719 breakpoint(); 618 breakpoint();
720 } 619 }
721 debug_only(if (paranoid) verify_block(memblock)); 620 debug_only(if (paranoid) verify_memory(ptr));
722 if (PrintMalloc && tty != NULL) tty->print_cr("os::malloc " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, memblock); 621 if (PrintMalloc && tty != NULL) {
723 622 tty->print_cr("os::malloc " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr);
724 // we do not track MallocCushion memory 623 }
725 MemTracker::record_malloc((address)memblock, size, memflags, caller == 0 ? CALLER_PC : caller); 624
726 625 // we do not track guard memory
727 return memblock; 626 MemTracker::record_malloc((address)ptr, size, memflags, caller == 0 ? CALLER_PC : caller);
627
628 return ptr;
728 } 629 }
729 630
730 631
731 void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, address caller) { 632 void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, address caller) {
732 #ifndef ASSERT 633 #ifndef ASSERT
741 tkr.discard(); 642 tkr.discard();
742 } 643 }
743 return ptr; 644 return ptr;
744 #else 645 #else
745 if (memblock == NULL) { 646 if (memblock == NULL) {
746 return malloc(size, memflags, (caller == 0 ? CALLER_PC : caller)); 647 return os::malloc(size, memflags, (caller == 0 ? CALLER_PC : caller));
747 } 648 }
748 if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { 649 if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) {
749 tty->print_cr("os::realloc caught " PTR_FORMAT, memblock); 650 tty->print_cr("os::realloc caught " PTR_FORMAT, memblock);
750 breakpoint(); 651 breakpoint();
751 } 652 }
752 verify_block(memblock); 653 verify_memory(memblock);
753 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); 654 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap());
754 if (size == 0) return NULL; 655 if (size == 0) {
656 return NULL;
657 }
755 // always move the block 658 // always move the block
756 void* ptr = malloc(size, memflags, caller == 0 ? CALLER_PC : caller); 659 void* ptr = os::malloc(size, memflags, caller == 0 ? CALLER_PC : caller);
757 if (PrintMalloc) tty->print_cr("os::remalloc " SIZE_FORMAT " bytes, " PTR_FORMAT " --> " PTR_FORMAT, size, memblock, ptr); 660 if (PrintMalloc) {
661 tty->print_cr("os::remalloc " SIZE_FORMAT " bytes, " PTR_FORMAT " --> " PTR_FORMAT, size, memblock, ptr);
662 }
758 // Copy to new memory if malloc didn't fail 663 // Copy to new memory if malloc didn't fail
759 if ( ptr != NULL ) { 664 if ( ptr != NULL ) {
760 memcpy(ptr, memblock, MIN2(size, get_size(memblock))); 665 GuardedMemory guarded(memblock);
761 if (paranoid) verify_block(ptr); 666 memcpy(ptr, memblock, MIN2(size, guarded.get_user_size()));
667 if (paranoid) verify_memory(ptr);
762 if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) { 668 if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) {
763 tty->print_cr("os::realloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr); 669 tty->print_cr("os::realloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr);
764 breakpoint(); 670 breakpoint();
765 } 671 }
766 free(memblock); 672 os::free(memblock);
767 } 673 }
768 return ptr; 674 return ptr;
769 #endif 675 #endif
770 } 676 }
771 677
772 678
773 void os::free(void *memblock, MEMFLAGS memflags) { 679 void os::free(void *memblock, MEMFLAGS memflags) {
680 address trackp = (address) memblock;
774 NOT_PRODUCT(inc_stat_counter(&num_frees, 1)); 681 NOT_PRODUCT(inc_stat_counter(&num_frees, 1));
775 #ifdef ASSERT 682 #ifdef ASSERT
776 if (memblock == NULL) return; 683 if (memblock == NULL) return;
777 if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) { 684 if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) {
778 if (tty != NULL) tty->print_cr("os::free caught " PTR_FORMAT, memblock); 685 if (tty != NULL) tty->print_cr("os::free caught " PTR_FORMAT, memblock);
779 breakpoint(); 686 breakpoint();
780 } 687 }
781 verify_block(memblock); 688 verify_memory(memblock);
782 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap()); 689 NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap());
783 // Added by detlefs. 690
784 if (MallocCushion) { 691 GuardedMemory guarded(memblock);
785 u_char* ptr = (u_char*)memblock - space_before; 692 size_t size = guarded.get_user_size();
786 for (u_char* p = ptr; p < ptr + MallocCushion; p++) { 693 inc_stat_counter(&free_bytes, size);
787 guarantee(*p == badResourceValue, 694 memblock = guarded.release_for_freeing();
788 "Thing freed should be malloc result."); 695 if (PrintMalloc && tty != NULL) {
789 *p = (u_char)freeBlockPad;
790 }
791 size_t size = get_size(memblock);
792 inc_stat_counter(&free_bytes, size);
793 u_char* end = ptr + space_before + size;
794 for (u_char* q = end; q < end + MallocCushion; q++) {
795 guarantee(*q == badResourceValue,
796 "Thing freed should be malloc result.");
797 *q = (u_char)freeBlockPad;
798 }
799 if (PrintMalloc && tty != NULL)
800 fprintf(stderr, "os::free " SIZE_FORMAT " bytes --> " PTR_FORMAT "\n", size, (uintptr_t)memblock); 696 fprintf(stderr, "os::free " SIZE_FORMAT " bytes --> " PTR_FORMAT "\n", size, (uintptr_t)memblock);
801 } else if (PrintMalloc && tty != NULL) { 697 }
802 // tty->print_cr("os::free %p", memblock); 698 #endif
803 fprintf(stderr, "os::free " PTR_FORMAT "\n", (uintptr_t)memblock); 699 MemTracker::record_free(trackp, memflags);
804 } 700
805 #endif 701 ::free(memblock);
806 MemTracker::record_free((address)memblock, memflags);
807
808 ::free((char*)memblock - space_before);
809 } 702 }
810 703
811 void os::init_random(long initval) { 704 void os::init_random(long initval) {
812 _rand_seed = initval; 705 _rand_seed = initval;
813 } 706 }