@@ -3215,9 +3215,10 @@ void os::split_reserved_memory(char *base, size_t size, size_t split) {
32153215 (attempt_reserve_memory_at (base, split) != NULL ) &&
32163216 (attempt_reserve_memory_at (split_address, size - split) != NULL );
32173217 if (!rc) {
3218- log_warning (os)(" os::split_reserved_memory failed for [ " RANGE_FORMAT " ) " ,
3218+ log_warning (os)(" os::split_reserved_memory failed for " RANGE_FORMAT,
32193219 RANGE_FORMAT_ARGS (base, size));
3220- assert (false , " os::split_reserved_memory failed for [" RANGE_FORMAT " )" ,
3220+ os::print_memory_mappings (base, size, tty);
3221+ assert (false , " os::split_reserved_memory failed for " RANGE_FORMAT,
32213222 RANGE_FORMAT_ARGS (base, size));
32223223 }
32233224
@@ -5989,19 +5990,55 @@ bool os::win32::find_mapping(address addr, mapping_info_t* mi) {
59895990 return rc;
59905991}
59915992
5993+ // Helper for print_one_mapping: print n words, both as hex and ascii.
5994+ // Use Safefetch for all values.
5995+ static void print_snippet (const void * p, outputStream* st) {
5996+ static const int num_words = LP64_ONLY (3 ) NOT_LP64 (6 );
5997+ static const int num_bytes = num_words * sizeof (int );
5998+ intptr_t v[num_words];
5999+ const int errval = 0xDE210244 ;
6000+ for (int i = 0 ; i < num_words; i++) {
6001+ v[i] = SafeFetchN ((intptr_t *)p + i, errval);
6002+ if (v[i] == errval &&
6003+ SafeFetchN ((intptr_t *)p + i, ~errval) == ~errval) {
6004+ return ;
6005+ }
6006+ }
6007+ st->put (' [' );
6008+ for (int i = 0 ; i < num_words; i++) {
6009+ st->print (INTPTR_FORMAT " " , v[i]);
6010+ }
6011+ const char * b = (char *)v;
6012+ st->put (' \" ' );
6013+ for (int i = 0 ; i < num_bytes; i++) {
6014+ st->put (::isgraph (b[i]) ? b[i] : ' .' );
6015+ }
6016+ st->put (' \" ' );
6017+ st->put (' ]' );
6018+ }
6019+
59926020// Helper function for print_memory_mappings:
59936021// Given a MEMORY_BASIC_INFORMATION, containing information about a non-free region:
59946022// print out all regions in that allocation. If any of those regions
59956023// fall outside the given range [start, end), indicate that in the output.
59966024// Return the pointer to the end of the allocation.
59976025static address print_one_mapping (MEMORY_BASIC_INFORMATION* minfo, address start, address end, outputStream* st) {
5998- assert (start != NULL && end != NULL && end > start, " Sanity" );
6026+ // Print it like this:
6027+ //
6028+ // Base: <xxxxx>: [xxxx - xxxx], state=MEM_xxx, prot=x, type=MEM_xxx (region 1)
6029+ // [xxxx - xxxx], state=MEM_xxx, prot=x, type=MEM_xxx (region 2)
59996030 assert (minfo->State != MEM_FREE, " Not inside an allocation." );
60006031 address allocation_base = (address)minfo->AllocationBase ;
6001- address last_region_end = NULL ;
6002- st->print_cr (" AllocationBase: " PTR_FORMAT " :" , allocation_base);
60036032 #define IS_IN (p ) (p >= start && p < end)
6033+ bool first_line = true ;
6034+ bool is_dll = false ;
60046035 for (;;) {
6036+ if (first_line) {
6037+ st->print (" Base " PTR_FORMAT " : " , p2i (allocation_base));
6038+ } else {
6039+ st->print_raw (NOT_LP64 (" " )
6040+ LP64_ONLY (" " ));
6041+ }
60056042 address region_start = (address)minfo->BaseAddress ;
60066043 address region_end = region_start + minfo->RegionSize ;
60076044 assert (region_end > region_start, " Sanity" );
@@ -6014,19 +6051,39 @@ static address print_one_mapping(MEMORY_BASIC_INFORMATION* minfo, address start,
60146051 }
60156052 st->print (" [" PTR_FORMAT " -" PTR_FORMAT " ), state=" , p2i (region_start), p2i (region_end));
60166053 switch (minfo->State ) {
6017- case MEM_COMMIT: st->print (" MEM_COMMIT" ); break ;
6018- case MEM_FREE: st->print (" MEM_FREE" ); break ;
6019- case MEM_RESERVE: st->print (" MEM_RESERVE" ); break ;
6054+ case MEM_COMMIT: st->print_raw (" MEM_COMMIT " ); break ;
6055+ case MEM_FREE: st->print_raw (" MEM_FREE " ); break ;
6056+ case MEM_RESERVE: st->print_raw (" MEM_RESERVE" ); break ;
60206057 default : st->print (" %x?" , (unsigned )minfo->State );
60216058 }
6022- st->print (" , prot=%x , type=" , (unsigned )minfo->AllocationProtect );
6059+ st->print (" , prot=%3x , type=" , (unsigned )minfo->Protect );
60236060 switch (minfo->Type ) {
6024- case MEM_IMAGE: st->print (" MEM_IMAGE" ); break ;
6025- case MEM_MAPPED: st->print (" MEM_MAPPED" ); break ;
6026- case MEM_PRIVATE: st->print (" MEM_PRIVATE" ); break ;
6061+ case MEM_IMAGE: st->print_raw (" MEM_IMAGE " ); break ;
6062+ case MEM_MAPPED: st->print_raw (" MEM_MAPPED " ); break ;
6063+ case MEM_PRIVATE: st->print_raw (" MEM_PRIVATE" ); break ;
60276064 default : st->print (" %x?" , (unsigned )minfo->State );
60286065 }
6066+ // At the start of every allocation, print some more information about this mapping.
6067+ // Notes:
6068+ // - this could be beefed up a lot, similar to os::print_location
6069+ // - for now we just query the allocation start point. This may be confusing for cases where
6070+ // the kernel merges multiple mappings.
6071+ if (first_line) {
6072+ char buf[MAX_PATH];
6073+ if (os::dll_address_to_library_name (allocation_base, buf, sizeof (buf), nullptr )) {
6074+ st->print (" , %s" , buf);
6075+ is_dll = true ;
6076+ }
6077+ }
6078+ // If memory is accessible, and we do not know anything else about it, print a snippet
6079+ if (!is_dll &&
6080+ minfo->State == MEM_COMMIT &&
6081+ !(minfo->Protect & PAGE_NOACCESS || minfo->Protect & PAGE_GUARD)) {
6082+ st->print_raw (" , " );
6083+ print_snippet (region_start, st);
6084+ }
60296085 st->cr ();
6086+ // Next region...
60306087 bool rc = checkedVirtualQuery (region_end, minfo);
60316088 if (rc == false || // VirtualQuery error, end of allocation?
60326089 (minfo->State == MEM_FREE) || // end of allocation, free memory follows
@@ -6035,6 +6092,7 @@ static address print_one_mapping(MEMORY_BASIC_INFORMATION* minfo, address start,
60356092 {
60366093 return region_end;
60376094 }
6095+ first_line = false ;
60386096 }
60396097 #undef IS_IN
60406098 ShouldNotReachHere ();
@@ -6046,7 +6104,14 @@ void os::print_memory_mappings(char* addr, size_t bytes, outputStream* st) {
60466104 address start = (address)addr;
60476105 address end = start + bytes;
60486106 address p = start;
6049- while (p < end) {
6107+ if (p == nullptr ) { // Lets skip the zero pages.
6108+ p += os::vm_allocation_granularity ();
6109+ }
6110+ address p2 = p; // guard against wraparounds
6111+ int fuse = 0 ;
6112+
6113+ while (p < end && p >= p2) {
6114+ p2 = p;
60506115 // Probe for the next mapping.
60516116 if (checkedVirtualQuery (p, &minfo)) {
60526117 if (minfo.State != MEM_FREE) {
@@ -6064,8 +6129,24 @@ void os::print_memory_mappings(char* addr, size_t bytes, outputStream* st) {
60646129 p = region_end;
60656130 }
60666131 } else {
6067- // advance probe pointer.
6068- p += os::vm_allocation_granularity ();
6132+ // MSDN doc on VirtualQuery is unclear about what it means if it returns an error.
6133+ // In particular, whether querying an address outside any mappings would report
6134+ // a MEM_FREE region or just return an error. From experiments, it seems to return
6135+ // a MEM_FREE region for unmapped areas in valid address space and an error if we
6136+ // are outside valid address space.
6137+ // Here, we advance the probe pointer by alloc granularity. But if the range to print
6138+ // is large, this may take a long time. Therefore lets stop right away if the address
6139+ // is outside of what we know are valid addresses on Windows. Also, add a loop fuse.
6140+ static const address end_virt = (address)(LP64_ONLY (0x7ffffffffffULL ) NOT_LP64 (3 *G));
6141+ if (p >= end_virt) {
6142+ break ;
6143+ } else {
6144+ // Advance probe pointer, but with a fuse to break long loops.
6145+ if (fuse++ == 100000 ) {
6146+ break ;
6147+ }
6148+ p += os::vm_allocation_granularity ();
6149+ }
60696150 }
60706151 }
60716152}
0 commit comments