Skip to content
Permalink
Browse files
8247514: Improve clhsdb 'findpc' ability to determine what an address…
… points to by improving PointerFinder and PointerLocation classes

Reviewed-by: ysuenaga, kevinw
  • Loading branch information
plummercj committed Feb 12, 2021
1 parent dc46aa8 commit e29c560a11c4cbc261bdd04db5d24170fb9f12b6
Showing 5 changed files with 284 additions and 54 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -267,7 +267,8 @@ public long getSize() {
}

public void printValueOn(PrintStream tty) {
tty.print("Method " + getName().asString() + getSignature().asString() + "@" + getAddress());
tty.print("Method " + getMethodHolder().getName().asString() + "." +
getName().asString() + getSignature().asString() + "@" + getAddress());
}

public void iterateFields(MetadataVisitor visitor) {
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -467,7 +467,7 @@ private Frame cookLastFrame(Frame fr) {
return fr;
}

private Address lastSPDbg() {
public Address lastSPDbg() {
return access.getLastSP(addr);
}

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,18 +26,74 @@

import sun.jvm.hotspot.code.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.gc.shared.*;
import sun.jvm.hotspot.interpreter.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.oops.Metadata;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.WrongTypeException;

/** This class, only intended for use in the debugging system,
provides the functionality of find() in the VM. */

public class PointerFinder {
public static PointerLocation find(Address a) {
PointerLocation loc = new PointerLocation(a);
Threads threads = VM.getVM().getThreads();

// Check if address is a pointer to a Metadata object.
try {
loc.metadata = Metadata.instantiateWrapperFor(a);
return loc;
} catch (Exception e) {
// Just ignore. This just means we aren't dealing with a Metadata pointer.
}

// Check if address is some other C++ type that we can deduce
loc.ctype = VM.getVM().getTypeDataBase().guessTypeForAddress(a);
if (loc.ctype == null && VM.getVM().isSharingEnabled()) {
// Check if the value falls in the _md_region
try {
Address loc1 = a.getAddressAt(0);
FileMapInfo cdsFileMapInfo = VM.getVM().getFileMapInfo();
if (cdsFileMapInfo.inCopiedVtableSpace(loc1)) {
loc.ctype = cdsFileMapInfo.getTypeForVptrAddress(loc1);
}
} catch (AddressException | WrongTypeException e) {
// This can happen if "a" or "loc1" is a bad address. Just ignore.
}
}
if (loc.ctype != null) {
return loc;
}

// Check if address is in the stack of a JavaThread
for (int i = 0; i < threads.getNumberOfThreads(); i++) {
JavaThread t = threads.getJavaThreadAt(i);
Address stackBase = t.getStackBase();
if (stackBase != null) {
Long stackSize = t.getStackSize();
Address stackEnd = stackBase.addOffsetTo(-stackSize);
if (a.lessThanOrEqual(stackBase) && a.greaterThan(stackEnd)) {
loc.stackThread = t;
return loc;
}
}
}

// Check if address is a native (C++) symbol
JVMDebugger dbg = VM.getVM().getDebugger();
CDebugger cdbg = dbg.getCDebugger();
if (cdbg != null) {
loc.loadObject = cdbg.loadObjectContainingPC(a);
if (loc.loadObject != null) {
loc.nativeSymbol = loc.loadObject.closestSymbolToPC(a);
return loc;
}
}

// Check if address is in the java heap.
CollectedHeap heap = VM.getVM().getUniverse().heap();
if (heap instanceof GenCollectedHeap) {
GenCollectedHeap genheap = (GenCollectedHeap) heap;
@@ -50,13 +106,12 @@ public static PointerLocation find(Address a) {
}
}

if (Assert.ASSERTS_ENABLED) {
if (Assert.ASSERTS_ENABLED) {
Assert.that(loc.gen != null, "Should have found this in a generation");
}

if (VM.getVM().getUseTLAB()) {
// Try to find thread containing it
Threads threads = VM.getVM().getThreads();
for (int i = 0; i < threads.getNumberOfThreads(); i++) {
JavaThread t = threads.getJavaThreadAt(i);
ThreadLocalAllocBuffer tlab = t.tlab();
@@ -78,13 +133,15 @@ public static PointerLocation find(Address a) {
}
}

// Check if address is in the interpreter
Interpreter interp = VM.getVM().getInterpreter();
if (interp.contains(a)) {
loc.inInterpreter = true;
loc.interpreterCodelet = interp.getCodeletContaining(a);
return loc;
}

// Check if address is in the code cache
if (!VM.getVM().isCore()) {
CodeCache c = VM.getVM().getCodeCache();
if (c.contains(a)) {
@@ -127,7 +184,6 @@ public static PointerLocation find(Address a) {
return loc;
}
// Look in thread-local handles
Threads threads = VM.getVM().getThreads();
for (int i = 0; i < threads.getNumberOfThreads(); i++) {
JavaThread t = threads.getJavaThreadAt(i);
JNIHandleBlock handleBlock = t.activeHandles();
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,10 +27,13 @@
import java.io.*;
import sun.jvm.hotspot.code.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.debugger.cdbg.*;
import sun.jvm.hotspot.gc.shared.*;
import sun.jvm.hotspot.interpreter.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.oops.Metadata;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.types.Type;

/** This class attempts to describe possible locations of pointers in
the VM. */
@@ -45,6 +48,13 @@ public class PointerLocation {

Address addr;

Metadata metadata;
Type ctype;
JavaThread stackThread;

LoadObject loadObject;
ClosestSymbol nativeSymbol;

CollectedHeap heap;
Generation gen;

@@ -80,6 +90,22 @@ public PointerLocation(Address addr) {
this.addr = addr;
}

public boolean isMetadata() {
return metadata != null;
}

public boolean isCtype() {
return ctype != null;
}

public boolean isInJavaStack() {
return stackThread != null;
}

public boolean isNativeSymbol() {
return loadObject != null;
}

public boolean isInHeap() {
return (heap != null || (gen != null));
}
@@ -175,8 +201,9 @@ public sun.jvm.hotspot.runtime.Thread getJNIHandleThread() {
}

public boolean isUnknown() {
return (!(isInHeap() || isInInterpreter() || isInCodeCache() ||
isInStrongGlobalJNIHandles() || isInWeakGlobalJNIHandles() || isInLocalJNIHandleBlock()));
return (!(isMetadata() || isCtype() || isInJavaStack() || isNativeSymbol() || isInHeap() ||
isInInterpreter() || isInCodeCache() || isInStrongGlobalJNIHandles() ||
isInWeakGlobalJNIHandles() || isInLocalJNIHandleBlock()));
}

public String toString() {
@@ -186,24 +213,66 @@ public String toString() {
}

public void print() {
printOn(System.out);
printOn(System.out, true, true);
}

public void print(boolean printAddress, boolean verbose) {
printOn(System.out, printAddress, verbose);
}

public void printOn(PrintStream tty) {
tty.print("Address ");
if (addr == null) {
tty.print("0x0");
} else {
tty.print(addr.toString());
printOn(tty, true, true);
}

public void printOn(PrintStream tty, boolean printAddress, boolean verbose) {
if (printAddress) {
tty.print("Address ");
if (addr == null) {
tty.print("0x0");
} else {
tty.print(addr.toString());
}
tty.print(": ");
}
tty.print(": ");
if (isInHeap()) {
if (isMetadata()) {
metadata.printValueOn(tty); // does not include "\n"
tty.println();
} else if (isCtype()) {
tty.println("Is of type " + ctype.getName());
} else if (isInJavaStack()) {
if (verbose) {
tty.format("In java stack [%s,%s,%s] for thread %s:\n ",
stackThread.getStackBase(), stackThread.lastSPDbg(),
stackThread.getStackBase().addOffsetTo(-stackThread.getStackSize()),
stackThread);
stackThread.printThreadInfoOn(tty); // includes "\n"
} else {
tty.format("In java stack for thread \"%s\" %s\n", stackThread.getThreadName(), stackThread);
}
} else if (isNativeSymbol()) {
CDebugger cdbg = VM.getVM().getDebugger().getCDebugger();
long diff;
if (nativeSymbol != null) {
String name = nativeSymbol.getName();
if (cdbg.canDemangle()) {
name = cdbg.demangle(name);
}
tty.print(name);
diff = nativeSymbol.getOffset();
} else {
tty.print(loadObject.getName());
diff = addr.minus(loadObject.getBase());
}
if (diff != 0L) {
tty.print(" + 0x" + Long.toHexString(diff));
}
tty.println();
} else if (isInHeap()) {
if (isInTLAB()) {
tty.print("In thread-local allocation buffer for thread \"" +
getTLABThread().getThreadName() + "\" (");
getTLABThread().printThreadIDOn(tty);
tty.print("In thread-local allocation buffer for thread (");
getTLABThread().printThreadInfoOn(tty);
tty.print(") ");
getTLAB().printOn(tty);
getTLAB().printOn(tty); // includes "\n"
} else {
if (isInNewGen()) {
tty.print("In new generation ");
@@ -213,13 +282,16 @@ public void printOn(PrintStream tty) {
tty.print("In unknown section of Java heap");
}
if (getGeneration() != null) {
getGeneration().printOn(tty);
getGeneration().printOn(tty); // does not include "\n"
}
tty.println();
}
} else if (isInInterpreter()) {
tty.println("In interpreter codelet \"" + interpreterCodelet.getDescription() + "\"");
interpreterCodelet.printOn(tty);
tty.print("In interpreter codelet: ");
interpreterCodelet.printOn(tty); // includes "\n"
} else if (isInCodeCache()) {
// TODO: print the type of CodeBlob. See "look for known code blobs" comment
// in PStack.java for example code.
CodeBlob b = getCodeBlob();
tty.print("In ");
if (isInBlobCode()) {
@@ -235,28 +307,32 @@ public void printOn(PrintStream tty) {
tty.print("unknown location");
}
tty.print(" in ");
b.printOn(tty);
if (verbose) {
b.printOn(tty); // includes "\n"
} else {
tty.println(b.toString());
}

// FIXME: add more detail
} else if (isInStrongGlobalJNIHandles()) {
tty.print("In JNI strong global");
tty.println("In JNI strong global");
} else if (isInWeakGlobalJNIHandles()) {
tty.print("In JNI weak global");
tty.println("In JNI weak global");
} else if (isInLocalJNIHandleBlock()) {
tty.print("In thread-local");
tty.print(" JNI handle block (" + handleBlock.top() + " handle slots present)");
if (handleThread.isJavaThread()) {
tty.print(" for JavaThread ");
((JavaThread) handleThread).printThreadIDOn(tty);
((JavaThread) handleThread).printThreadIDOn(tty); // includes "\n"
} else {
tty.print(" for a non-Java Thread");
tty.println(" for a non-Java Thread");
}
} else {
// This must be last
if (Assert.ASSERTS_ENABLED) {
Assert.that(isUnknown(), "Should have unknown location");
}
tty.print("In unknown location");
tty.println("In unknown location");
}
}
}

1 comment on commit e29c560

@openjdk-notifier
Copy link

@openjdk-notifier openjdk-notifier bot commented on e29c560 Feb 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.