8281023: NMT integration into pp debug command does not work
Reviewed-by: zgu, iklam
This commit is contained in:
parent
63a00a0df2
commit
010965c86a
src/hotspot/share
@ -24,6 +24,7 @@
|
||||
#include "precompiled.hpp"
|
||||
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/safefetch.inline.hpp"
|
||||
#include "services/mallocSiteTable.hpp"
|
||||
#include "services/mallocTracker.hpp"
|
||||
#include "services/mallocTracker.inline.hpp"
|
||||
@ -289,3 +290,32 @@ void* MallocTracker::record_free(void* memblock) {
|
||||
header->release();
|
||||
return (void*)header;
|
||||
}
|
||||
|
||||
// Given a pointer, if it seems to point to the start of a valid malloced block,
|
||||
// print the block. Note that since there is very low risk of memory looking
|
||||
// accidentally like a valid malloc block header (canaries and all) this is not
|
||||
// totally failproof. Only use this during debugging or when you can afford
|
||||
// signals popping up, e.g. when writing an hs_err file.
|
||||
bool MallocTracker::print_pointer_information(const void* p, outputStream* st) {
|
||||
assert(MemTracker::enabled(), "NMT must be enabled");
|
||||
if (CanUseSafeFetch32() && os::is_readable_pointer(p)) {
|
||||
const NMT_TrackingLevel tracking_level = MemTracker::tracking_level();
|
||||
const MallocHeader* mhdr = (const MallocHeader*)MallocTracker::get_base(const_cast<void*>(p), tracking_level);
|
||||
char msg[256];
|
||||
address p_corrupted;
|
||||
if (os::is_readable_pointer(mhdr) &&
|
||||
mhdr->check_block_integrity(msg, sizeof(msg), &p_corrupted)) {
|
||||
st->print_cr(PTR_FORMAT " malloc'd " SIZE_FORMAT " bytes by %s",
|
||||
p2i(p), mhdr->size(), NMTUtil::flag_to_name(mhdr->flags()));
|
||||
if (tracking_level == NMT_detail) {
|
||||
NativeCallStack ncs;
|
||||
if (mhdr->get_stack(ncs)) {
|
||||
ncs.print_on(st);
|
||||
st->cr();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include "services/nmtCommon.hpp"
|
||||
#include "utilities/nativeCallStack.hpp"
|
||||
|
||||
class outputStream;
|
||||
|
||||
/*
|
||||
* This counter class counts memory allocation and deallocation,
|
||||
* records total memory allocation size and number of allocations.
|
||||
@ -438,6 +440,14 @@ class MallocTracker : AllStatic {
|
||||
static inline void record_arena_size_change(ssize_t size, MEMFLAGS flags) {
|
||||
MallocMemorySummary::record_arena_size_change(size, flags);
|
||||
}
|
||||
|
||||
// Given a pointer, if it seems to point to the start of a valid malloced block,
|
||||
// print the block. Note that since there is very low risk of memory looking
|
||||
// accidentally like a valid malloc block header (canaries and all) this is not
|
||||
// totally failproof. Only use this during debugging or when you can afford
|
||||
// signals popping up, e.g. when writing an hs_err file.
|
||||
static bool print_pointer_information(const void* p, outputStream* st);
|
||||
|
||||
private:
|
||||
static inline MallocHeader* malloc_header(void *memblock) {
|
||||
assert(memblock != NULL, "NULL pointer");
|
||||
|
@ -672,28 +672,32 @@ bool VirtualMemoryTracker::walk_virtual_memory(VirtualMemoryWalker* walker) {
|
||||
return true;
|
||||
}
|
||||
|
||||
class FindAndSnapshotRegionWalker : public VirtualMemoryWalker {
|
||||
class PrintRegionWalker : public VirtualMemoryWalker {
|
||||
private:
|
||||
ReservedMemoryRegion& _region;
|
||||
const address _p;
|
||||
bool _found_region;
|
||||
const address _p;
|
||||
outputStream* _st;
|
||||
public:
|
||||
FindAndSnapshotRegionWalker(void* p, ReservedMemoryRegion& region) :
|
||||
_region(region), _p((address)p), _found_region(false) { }
|
||||
PrintRegionWalker(const void* p, outputStream* st) :
|
||||
_p((address)p), _st(st) { }
|
||||
|
||||
bool do_allocation_site(const ReservedMemoryRegion* rgn) {
|
||||
if (rgn->contain_address(_p)) {
|
||||
_region = *rgn;
|
||||
_found_region = true;
|
||||
_st->print_cr(PTR_FORMAT " in mmap'd memory region [" PTR_FORMAT " - " PTR_FORMAT "] by %s",
|
||||
p2i(_p), p2i(rgn->base()), p2i(rgn->base() + rgn->size()), rgn->flag_name());
|
||||
if (MemTracker::tracking_level() == NMT_detail) {
|
||||
rgn->call_stack()->print_on(_st);
|
||||
_st->cr();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool found_region() const { return _found_region; }
|
||||
};
|
||||
|
||||
const bool VirtualMemoryTracker::snapshot_region_contains(void* p, ReservedMemoryRegion& region) {
|
||||
FindAndSnapshotRegionWalker walker(p, region);
|
||||
walk_virtual_memory(&walker);
|
||||
return walker.found_region();
|
||||
// If p is contained within a known memory region, print information about it to the
|
||||
// given stream and return true; false otherwise.
|
||||
bool VirtualMemoryTracker::print_containing_region(const void* p, outputStream* st) {
|
||||
PrintRegionWalker walker(p, st);
|
||||
return !walk_virtual_memory(&walker);
|
||||
|
||||
}
|
||||
|
@ -385,7 +385,9 @@ class VirtualMemoryTracker : AllStatic {
|
||||
// Walk virtual memory data structure for creating baseline, etc.
|
||||
static bool walk_virtual_memory(VirtualMemoryWalker* walker);
|
||||
|
||||
static const bool snapshot_region_contains(void* p, ReservedMemoryRegion& region);
|
||||
// If p is contained within a known memory region, print information about it to the
|
||||
// given stream and return true; false otherwise.
|
||||
static bool print_containing_region(const void* p, outputStream* st);
|
||||
|
||||
// Snapshot current thread stacks
|
||||
static void snapshot_thread_stacks();
|
||||
|
@ -44,7 +44,6 @@
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "runtime/java.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/safefetch.inline.hpp"
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
#include "runtime/stubCodeGenerator.hpp"
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
@ -483,39 +482,23 @@ extern "C" JNIEXPORT void pp(void* p) {
|
||||
oop obj = cast_to_oop(p);
|
||||
obj->print();
|
||||
} else {
|
||||
// Ask NMT about this pointer.
|
||||
// GDB note: We will be using SafeFetch to access the supposed malloc header. If the address is
|
||||
// not readable, this will generate a signal. That signal will trip up the debugger: gdb will
|
||||
// catch the signal and disable the pp() command for further use.
|
||||
// In order to avoid that, switch off SIGSEGV handling with "handle SIGSEGV nostop" before
|
||||
// invoking pp()
|
||||
if (MemTracker::enabled()) {
|
||||
const NMT_TrackingLevel tracking_level = MemTracker::tracking_level();
|
||||
ReservedMemoryRegion region(0, 0);
|
||||
// Check and snapshot a mmap'd region that contains the pointer
|
||||
if (VirtualMemoryTracker::snapshot_region_contains(p, region)) {
|
||||
tty->print_cr(PTR_FORMAT " in mmap'd memory region [" PTR_FORMAT " - " PTR_FORMAT "] by %s",
|
||||
p2i(p), p2i(region.base()), p2i(region.base() + region.size()), region.flag_name());
|
||||
if (tracking_level == NMT_detail) {
|
||||
region.call_stack()->print_on(tty);
|
||||
tty->cr();
|
||||
}
|
||||
// Does it point into a known mmaped region?
|
||||
if (VirtualMemoryTracker::print_containing_region(p, tty)) {
|
||||
return;
|
||||
}
|
||||
// Check if it is a malloc'd memory block
|
||||
if (CanUseSafeFetchN() && SafeFetchN((intptr_t*)p, 0) != 0) {
|
||||
const MallocHeader* mhdr = (const MallocHeader*)MallocTracker::get_base(p, tracking_level);
|
||||
char msg[256];
|
||||
address p_corrupted;
|
||||
if (SafeFetchN((intptr_t*)mhdr, 0) != 0 && mhdr->check_block_integrity(msg, sizeof(msg), &p_corrupted)) {
|
||||
tty->print_cr(PTR_FORMAT " malloc'd " SIZE_FORMAT " bytes by %s",
|
||||
p2i(p), mhdr->size(), NMTUtil::flag_to_name(mhdr->flags()));
|
||||
if (tracking_level == NMT_detail) {
|
||||
NativeCallStack ncs;
|
||||
if (mhdr->get_stack(ncs)) {
|
||||
ncs.print_on(tty);
|
||||
tty->cr();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Does it look like the start of a malloced block?
|
||||
if (MallocTracker::print_pointer_information(p, tty)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
tty->print(PTR_FORMAT, p2i(p));
|
||||
tty->print_cr(PTR_FORMAT, p2i(p));
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user