8247514: Improve clhsdb 'findpc' ability to determine what an address points to by improving PointerFinder and PointerLocation classes
Reviewed-by: ysuenaga, kevinw
This commit is contained in:
parent
dc46aa85c6
commit
e29c560a11
@ -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 class Method extends Metadata {
|
||||
}
|
||||
|
||||
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 @@ public class JavaThread extends Thread {
|
||||
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,10 +26,13 @@ package sun.jvm.hotspot.utilities;
|
||||
|
||||
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. */
|
||||
@ -37,7 +40,60 @@ import sun.jvm.hotspot.memory.*;
|
||||
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 class PointerFinder {
|
||||
}
|
||||
}
|
||||
|
||||
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,6 +133,7 @@ public class PointerFinder {
|
||||
}
|
||||
}
|
||||
|
||||
// Check if address is in the interpreter
|
||||
Interpreter interp = VM.getVM().getInterpreter();
|
||||
if (interp.contains(a)) {
|
||||
loc.inInterpreter = true;
|
||||
@ -85,6 +141,7 @@ public class PointerFinder {
|
||||
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 class PointerFinder {
|
||||
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 @@ package sun.jvm.hotspot.utilities;
|
||||
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 class PointerLocation {
|
||||
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 class PointerLocation {
|
||||
}
|
||||
|
||||
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 class PointerLocation {
|
||||
}
|
||||
|
||||
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 class PointerLocation {
|
||||
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 class PointerLocation {
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import java.util.Map;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import jdk.test.lib.apps.LingeredApp;
|
||||
import jdk.test.lib.Platform;
|
||||
import jdk.test.lib.util.CoreUtils;
|
||||
import jtreg.SkippedException;
|
||||
|
||||
@ -75,12 +76,18 @@ import jtreg.SkippedException;
|
||||
*/
|
||||
|
||||
public class ClhsdbFindPC {
|
||||
static LingeredApp theApp = null;
|
||||
static String coreFileName = null;
|
||||
static ClhsdbLauncher test = null;
|
||||
|
||||
private static void testFindPC(boolean withXcomp, boolean withCore) throws Exception {
|
||||
LingeredApp theApp = null;
|
||||
String coreFileName = null;
|
||||
try {
|
||||
ClhsdbLauncher test = new ClhsdbLauncher();
|
||||
String segvAddress = null;
|
||||
List<String> cmds = null;
|
||||
String cmdStr = null;
|
||||
Map<String, List<String>> expStrMap = null;
|
||||
|
||||
test = new ClhsdbLauncher();
|
||||
|
||||
theApp = new LingeredAppWithTrivialMain();
|
||||
theApp.setForceCrash(withCore);
|
||||
@ -97,24 +104,38 @@ public class ClhsdbFindPC {
|
||||
}
|
||||
System.out.println("with pid " + theApp.getPid());
|
||||
|
||||
// Get the core file name if we are debugging a core instead of live process
|
||||
if (withCore) {
|
||||
coreFileName = CoreUtils.getCoreFileLocation(theApp.getOutput().getStdout(), theApp.getPid());
|
||||
String crashOutput = theApp.getOutput().getStdout();
|
||||
// Get the core file name if we are debugging a core instead of live process
|
||||
coreFileName = CoreUtils.getCoreFileLocation(crashOutput, theApp.getPid());
|
||||
// Get the SEGV Address from the following line:
|
||||
// # SIGSEGV (0xb) at pc=0x00007f20a897f7f4, pid=8561, tid=8562
|
||||
String[] parts = crashOutput.split(" pc=");
|
||||
String[] tokens = parts[1].split(",");
|
||||
segvAddress = tokens[0];
|
||||
|
||||
// Test the 'findpc' command passing in the SEGV address
|
||||
cmds = new ArrayList<String>();
|
||||
cmdStr = "findpc " + segvAddress;
|
||||
cmds.add(cmdStr);
|
||||
expStrMap = new HashMap<>();
|
||||
if (Platform.isOSX()) {
|
||||
// OSX will only find addresses in JVM libraries, not user or system libraries
|
||||
expStrMap.put(cmdStr, List.of("In unknown location"));
|
||||
} else { // symbol lookups not supported with OSX live process
|
||||
expStrMap.put(cmdStr, List.of("Java_jdk_test_lib_apps_LingeredApp_crash"));
|
||||
}
|
||||
runTest(withCore, cmds, expStrMap);
|
||||
}
|
||||
|
||||
// Run 'jstack -v' command to get the findpc address
|
||||
List<String> cmds = List.of("jstack -v");
|
||||
String output;
|
||||
if (withCore) {
|
||||
output = test.runOnCore(coreFileName, cmds, null, null);
|
||||
} else {
|
||||
output = test.run(theApp.getPid(), cmds, null, null);
|
||||
}
|
||||
// Run 'jstack -v' command to get the pc and other useful values
|
||||
cmds = List.of("jstack -v");
|
||||
String jStackOutput = runTest(withCore, cmds, null);
|
||||
|
||||
// Extract pc address from the following line:
|
||||
// - LingeredAppWithTrivialMain.main(java.lang.String[]) @bci=1, line=33, pc=0x00007ff18ff519f0, ...
|
||||
String pcAddress = null;
|
||||
String[] parts = output.split("LingeredAppWithTrivialMain.main");
|
||||
String[] parts = jStackOutput.split("LingeredAppWithTrivialMain.main");
|
||||
String[] tokens = parts[1].split(" ");
|
||||
for (String token : tokens) {
|
||||
if (token.contains("pc")) {
|
||||
@ -128,11 +149,11 @@ public class ClhsdbFindPC {
|
||||
throw new RuntimeException("Cannot find LingeredAppWithTrivialMain.main pc in output");
|
||||
}
|
||||
|
||||
// Test the 'findpc' command passing in the pc obtained from above
|
||||
// Test the 'findpc' command passing in the pc obtained from jstack above
|
||||
cmds = new ArrayList<String>();
|
||||
String cmdStr = "findpc " + pcAddress;
|
||||
cmdStr = "findpc " + pcAddress;
|
||||
cmds.add(cmdStr);
|
||||
Map<String, List<String>> expStrMap = new HashMap<>();
|
||||
expStrMap = new HashMap<>();
|
||||
if (withXcomp) {
|
||||
expStrMap.put(cmdStr, List.of(
|
||||
"In code in NMethod for LingeredAppWithTrivialMain.main",
|
||||
@ -143,12 +164,78 @@ public class ClhsdbFindPC {
|
||||
expStrMap.put(cmdStr, List.of(
|
||||
"In interpreter codelet"));
|
||||
}
|
||||
runTest(withCore, cmds, expStrMap);
|
||||
|
||||
if (withCore) {
|
||||
test.runOnCore(coreFileName, cmds, expStrMap, null);
|
||||
// Run findpc on a Method*. We can find one in the jstack output. For example:
|
||||
// - LingeredAppWithTrivialMain.main(java.lang.String[]) @bci=1, line=33, pc=..., Method*=0x0000008041000208 ...
|
||||
// This is testing the PointerFinder support for C++ MetaData types.
|
||||
parts = jStackOutput.split("LingeredAppWithTrivialMain.main");
|
||||
parts = parts[1].split("Method\\*=");
|
||||
parts = parts[1].split(" ");
|
||||
String methodAddr = parts[0];
|
||||
cmdStr = "findpc " + methodAddr;
|
||||
cmds = List.of(cmdStr);
|
||||
expStrMap = new HashMap<>();
|
||||
expStrMap.put(cmdStr, List.of("Method ",
|
||||
"LingeredAppWithTrivialMain.main",
|
||||
methodAddr));
|
||||
runTest(withCore, cmds, expStrMap);
|
||||
|
||||
// Run findpc on a JavaThread*. We can find one in the jstack output.
|
||||
// The tid for a thread is it's JavaThread*. For example:
|
||||
// "main" #1 prio=5 tid=0x00000080263398f0 nid=0x277e0 ...
|
||||
// This is testing the PointerFinder support for all C++ types other than MetaData types.
|
||||
parts = jStackOutput.split("tid=");
|
||||
parts = parts[1].split(" ");
|
||||
String tid = parts[0]; // address of the JavaThread
|
||||
cmdStr = "findpc " + tid;
|
||||
cmds = List.of(cmdStr);
|
||||
expStrMap = new HashMap<>();
|
||||
expStrMap.put(cmdStr, List.of("Is of type JavaThread"));
|
||||
runTest(withCore, cmds, expStrMap);
|
||||
|
||||
// Run findpc on a java stack address. We can find one in the jstack output.
|
||||
// "main" #1 prio=5 tid=... nid=0x277e0 waiting on condition [0x0000008025aef000]
|
||||
// The stack address is the last word between the brackets.
|
||||
// This is testing the PointerFinder support for thread stack addresses.
|
||||
parts = jStackOutput.split("tid=");
|
||||
parts = parts[1].split(" \\[");
|
||||
parts = parts[1].split("\\]");
|
||||
String stackAddress = parts[0]; // address of the thread's stack
|
||||
cmdStr = "findpc " + stackAddress;
|
||||
cmds = List.of(cmdStr);
|
||||
expStrMap = new HashMap<>();
|
||||
expStrMap.put(cmdStr, List.of("In java stack"));
|
||||
runTest(withCore, cmds, expStrMap);
|
||||
|
||||
// Run 'examine <addr>' using a thread's tid as the address. The
|
||||
// examine output will be the of the form:
|
||||
// <tid>: <value>
|
||||
// Where <value> is the word stored at <tid>. <value> also happens to
|
||||
// be the vtable address. We then run findpc on this vtable address.
|
||||
// This tests PointerFinder support for native C++ symbols.
|
||||
cmds = List.of("examine " + tid);
|
||||
String examineOutput = runTest(withCore, cmds, null);
|
||||
// Extract <value>.
|
||||
parts = examineOutput.split(tid + ": ");
|
||||
String value = parts[1];
|
||||
// Use findpc on <value>. The output should look something like:
|
||||
// Address 0x00007fed86f610b8: vtable for JavaThread + 0x10
|
||||
cmdStr = "findpc " + value;
|
||||
cmds = List.of(cmdStr);
|
||||
expStrMap = new HashMap<>();
|
||||
if (Platform.isWindows()) {
|
||||
expStrMap.put(cmdStr, List.of("jvm.+JavaThread"));
|
||||
} else if (Platform.isOSX()) {
|
||||
if (withCore) {
|
||||
expStrMap.put(cmdStr, List.of("__ZTV10JavaThread"));
|
||||
} else { // symbol lookups not supported with OSX live process
|
||||
expStrMap.put(cmdStr, List.of("In unknown location"));
|
||||
}
|
||||
} else {
|
||||
test.run(theApp.getPid(), cmds, expStrMap, null);
|
||||
expStrMap.put(cmdStr, List.of("vtable for JavaThread"));
|
||||
}
|
||||
runTest(withCore, cmds, expStrMap);
|
||||
} catch (SkippedException se) {
|
||||
throw se;
|
||||
} catch (Exception ex) {
|
||||
@ -160,6 +247,16 @@ public class ClhsdbFindPC {
|
||||
}
|
||||
}
|
||||
|
||||
private static String runTest(boolean withCore, List<String> cmds, Map<String, List<String>> expStrMap)
|
||||
throws Exception
|
||||
{
|
||||
if (withCore) {
|
||||
return test.runOnCore(coreFileName, cmds, expStrMap, null);
|
||||
} else {
|
||||
return test.run(theApp.getPid(), cmds, expStrMap, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
boolean withXcomp = Boolean.parseBoolean(args[0]);
|
||||
boolean withCore = Boolean.parseBoolean(args[1]);
|
||||
|
Loading…
Reference in New Issue
Block a user