Skip to content

Commit e29c560

Browse files
committed
8247514: Improve clhsdb 'findpc' ability to determine what an address points to by improving PointerFinder and PointerLocation classes
Reviewed-by: ysuenaga, kevinw
1 parent dc46aa8 commit e29c560

File tree

5 files changed

+284
-54
lines changed

5 files changed

+284
-54
lines changed

src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Method.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -267,7 +267,8 @@ public long getSize() {
267267
}
268268

269269
public void printValueOn(PrintStream tty) {
270-
tty.print("Method " + getName().asString() + getSignature().asString() + "@" + getAddress());
270+
tty.print("Method " + getMethodHolder().getName().asString() + "." +
271+
getName().asString() + getSignature().asString() + "@" + getAddress());
271272
}
272273

273274
public void iterateFields(MetadataVisitor visitor) {

src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -467,7 +467,7 @@ private Frame cookLastFrame(Frame fr) {
467467
return fr;
468468
}
469469

470-
private Address lastSPDbg() {
470+
public Address lastSPDbg() {
471471
return access.getLastSP(addr);
472472
}
473473

src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerFinder.java

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -26,18 +26,74 @@
2626

2727
import sun.jvm.hotspot.code.*;
2828
import sun.jvm.hotspot.debugger.*;
29+
import sun.jvm.hotspot.debugger.cdbg.*;
2930
import sun.jvm.hotspot.gc.shared.*;
3031
import sun.jvm.hotspot.interpreter.*;
31-
import sun.jvm.hotspot.runtime.*;
3232
import sun.jvm.hotspot.memory.*;
33+
import sun.jvm.hotspot.oops.Metadata;
34+
import sun.jvm.hotspot.runtime.*;
35+
import sun.jvm.hotspot.types.WrongTypeException;
3336

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

3740
public class PointerFinder {
3841
public static PointerLocation find(Address a) {
3942
PointerLocation loc = new PointerLocation(a);
43+
Threads threads = VM.getVM().getThreads();
44+
45+
// Check if address is a pointer to a Metadata object.
46+
try {
47+
loc.metadata = Metadata.instantiateWrapperFor(a);
48+
return loc;
49+
} catch (Exception e) {
50+
// Just ignore. This just means we aren't dealing with a Metadata pointer.
51+
}
52+
53+
// Check if address is some other C++ type that we can deduce
54+
loc.ctype = VM.getVM().getTypeDataBase().guessTypeForAddress(a);
55+
if (loc.ctype == null && VM.getVM().isSharingEnabled()) {
56+
// Check if the value falls in the _md_region
57+
try {
58+
Address loc1 = a.getAddressAt(0);
59+
FileMapInfo cdsFileMapInfo = VM.getVM().getFileMapInfo();
60+
if (cdsFileMapInfo.inCopiedVtableSpace(loc1)) {
61+
loc.ctype = cdsFileMapInfo.getTypeForVptrAddress(loc1);
62+
}
63+
} catch (AddressException | WrongTypeException e) {
64+
// This can happen if "a" or "loc1" is a bad address. Just ignore.
65+
}
66+
}
67+
if (loc.ctype != null) {
68+
return loc;
69+
}
70+
71+
// Check if address is in the stack of a JavaThread
72+
for (int i = 0; i < threads.getNumberOfThreads(); i++) {
73+
JavaThread t = threads.getJavaThreadAt(i);
74+
Address stackBase = t.getStackBase();
75+
if (stackBase != null) {
76+
Long stackSize = t.getStackSize();
77+
Address stackEnd = stackBase.addOffsetTo(-stackSize);
78+
if (a.lessThanOrEqual(stackBase) && a.greaterThan(stackEnd)) {
79+
loc.stackThread = t;
80+
return loc;
81+
}
82+
}
83+
}
4084

85+
// Check if address is a native (C++) symbol
86+
JVMDebugger dbg = VM.getVM().getDebugger();
87+
CDebugger cdbg = dbg.getCDebugger();
88+
if (cdbg != null) {
89+
loc.loadObject = cdbg.loadObjectContainingPC(a);
90+
if (loc.loadObject != null) {
91+
loc.nativeSymbol = loc.loadObject.closestSymbolToPC(a);
92+
return loc;
93+
}
94+
}
95+
96+
// Check if address is in the java heap.
4197
CollectedHeap heap = VM.getVM().getUniverse().heap();
4298
if (heap instanceof GenCollectedHeap) {
4399
GenCollectedHeap genheap = (GenCollectedHeap) heap;
@@ -50,13 +106,12 @@ public static PointerLocation find(Address a) {
50106
}
51107
}
52108

53-
if (Assert.ASSERTS_ENABLED) {
109+
if (Assert.ASSERTS_ENABLED) {
54110
Assert.that(loc.gen != null, "Should have found this in a generation");
55111
}
56112

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

136+
// Check if address is in the interpreter
81137
Interpreter interp = VM.getVM().getInterpreter();
82138
if (interp.contains(a)) {
83139
loc.inInterpreter = true;
84140
loc.interpreterCodelet = interp.getCodeletContaining(a);
85141
return loc;
86142
}
87143

144+
// Check if address is in the code cache
88145
if (!VM.getVM().isCore()) {
89146
CodeCache c = VM.getVM().getCodeCache();
90147
if (c.contains(a)) {
@@ -127,7 +184,6 @@ public static PointerLocation find(Address a) {
127184
return loc;
128185
}
129186
// Look in thread-local handles
130-
Threads threads = VM.getVM().getThreads();
131187
for (int i = 0; i < threads.getNumberOfThreads(); i++) {
132188
JavaThread t = threads.getJavaThreadAt(i);
133189
JNIHandleBlock handleBlock = t.activeHandles();

src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/PointerLocation.java

Lines changed: 101 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -27,10 +27,13 @@
2727
import java.io.*;
2828
import sun.jvm.hotspot.code.*;
2929
import sun.jvm.hotspot.debugger.*;
30+
import sun.jvm.hotspot.debugger.cdbg.*;
3031
import sun.jvm.hotspot.gc.shared.*;
3132
import sun.jvm.hotspot.interpreter.*;
32-
import sun.jvm.hotspot.runtime.*;
3333
import sun.jvm.hotspot.memory.*;
34+
import sun.jvm.hotspot.oops.Metadata;
35+
import sun.jvm.hotspot.runtime.*;
36+
import sun.jvm.hotspot.types.Type;
3437

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

4649
Address addr;
4750

51+
Metadata metadata;
52+
Type ctype;
53+
JavaThread stackThread;
54+
55+
LoadObject loadObject;
56+
ClosestSymbol nativeSymbol;
57+
4858
CollectedHeap heap;
4959
Generation gen;
5060

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

93+
public boolean isMetadata() {
94+
return metadata != null;
95+
}
96+
97+
public boolean isCtype() {
98+
return ctype != null;
99+
}
100+
101+
public boolean isInJavaStack() {
102+
return stackThread != null;
103+
}
104+
105+
public boolean isNativeSymbol() {
106+
return loadObject != null;
107+
}
108+
83109
public boolean isInHeap() {
84110
return (heap != null || (gen != null));
85111
}
@@ -175,8 +201,9 @@ public sun.jvm.hotspot.runtime.Thread getJNIHandleThread() {
175201
}
176202

177203
public boolean isUnknown() {
178-
return (!(isInHeap() || isInInterpreter() || isInCodeCache() ||
179-
isInStrongGlobalJNIHandles() || isInWeakGlobalJNIHandles() || isInLocalJNIHandleBlock()));
204+
return (!(isMetadata() || isCtype() || isInJavaStack() || isNativeSymbol() || isInHeap() ||
205+
isInInterpreter() || isInCodeCache() || isInStrongGlobalJNIHandles() ||
206+
isInWeakGlobalJNIHandles() || isInLocalJNIHandleBlock()));
180207
}
181208

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

188215
public void print() {
189-
printOn(System.out);
216+
printOn(System.out, true, true);
217+
}
218+
219+
public void print(boolean printAddress, boolean verbose) {
220+
printOn(System.out, printAddress, verbose);
190221
}
191222

192223
public void printOn(PrintStream tty) {
193-
tty.print("Address ");
194-
if (addr == null) {
195-
tty.print("0x0");
196-
} else {
197-
tty.print(addr.toString());
224+
printOn(tty, true, true);
225+
}
226+
227+
public void printOn(PrintStream tty, boolean printAddress, boolean verbose) {
228+
if (printAddress) {
229+
tty.print("Address ");
230+
if (addr == null) {
231+
tty.print("0x0");
232+
} else {
233+
tty.print(addr.toString());
234+
}
235+
tty.print(": ");
198236
}
199-
tty.print(": ");
200-
if (isInHeap()) {
237+
if (isMetadata()) {
238+
metadata.printValueOn(tty); // does not include "\n"
239+
tty.println();
240+
} else if (isCtype()) {
241+
tty.println("Is of type " + ctype.getName());
242+
} else if (isInJavaStack()) {
243+
if (verbose) {
244+
tty.format("In java stack [%s,%s,%s] for thread %s:\n ",
245+
stackThread.getStackBase(), stackThread.lastSPDbg(),
246+
stackThread.getStackBase().addOffsetTo(-stackThread.getStackSize()),
247+
stackThread);
248+
stackThread.printThreadInfoOn(tty); // includes "\n"
249+
} else {
250+
tty.format("In java stack for thread \"%s\" %s\n", stackThread.getThreadName(), stackThread);
251+
}
252+
} else if (isNativeSymbol()) {
253+
CDebugger cdbg = VM.getVM().getDebugger().getCDebugger();
254+
long diff;
255+
if (nativeSymbol != null) {
256+
String name = nativeSymbol.getName();
257+
if (cdbg.canDemangle()) {
258+
name = cdbg.demangle(name);
259+
}
260+
tty.print(name);
261+
diff = nativeSymbol.getOffset();
262+
} else {
263+
tty.print(loadObject.getName());
264+
diff = addr.minus(loadObject.getBase());
265+
}
266+
if (diff != 0L) {
267+
tty.print(" + 0x" + Long.toHexString(diff));
268+
}
269+
tty.println();
270+
} else if (isInHeap()) {
201271
if (isInTLAB()) {
202-
tty.print("In thread-local allocation buffer for thread \"" +
203-
getTLABThread().getThreadName() + "\" (");
204-
getTLABThread().printThreadIDOn(tty);
272+
tty.print("In thread-local allocation buffer for thread (");
273+
getTLABThread().printThreadInfoOn(tty);
205274
tty.print(") ");
206-
getTLAB().printOn(tty);
275+
getTLAB().printOn(tty); // includes "\n"
207276
} else {
208277
if (isInNewGen()) {
209278
tty.print("In new generation ");
@@ -213,13 +282,16 @@ public void printOn(PrintStream tty) {
213282
tty.print("In unknown section of Java heap");
214283
}
215284
if (getGeneration() != null) {
216-
getGeneration().printOn(tty);
285+
getGeneration().printOn(tty); // does not include "\n"
217286
}
287+
tty.println();
218288
}
219289
} else if (isInInterpreter()) {
220-
tty.println("In interpreter codelet \"" + interpreterCodelet.getDescription() + "\"");
221-
interpreterCodelet.printOn(tty);
290+
tty.print("In interpreter codelet: ");
291+
interpreterCodelet.printOn(tty); // includes "\n"
222292
} else if (isInCodeCache()) {
293+
// TODO: print the type of CodeBlob. See "look for known code blobs" comment
294+
// in PStack.java for example code.
223295
CodeBlob b = getCodeBlob();
224296
tty.print("In ");
225297
if (isInBlobCode()) {
@@ -235,28 +307,32 @@ public void printOn(PrintStream tty) {
235307
tty.print("unknown location");
236308
}
237309
tty.print(" in ");
238-
b.printOn(tty);
310+
if (verbose) {
311+
b.printOn(tty); // includes "\n"
312+
} else {
313+
tty.println(b.toString());
314+
}
239315

240316
// FIXME: add more detail
241317
} else if (isInStrongGlobalJNIHandles()) {
242-
tty.print("In JNI strong global");
318+
tty.println("In JNI strong global");
243319
} else if (isInWeakGlobalJNIHandles()) {
244-
tty.print("In JNI weak global");
320+
tty.println("In JNI weak global");
245321
} else if (isInLocalJNIHandleBlock()) {
246322
tty.print("In thread-local");
247323
tty.print(" JNI handle block (" + handleBlock.top() + " handle slots present)");
248324
if (handleThread.isJavaThread()) {
249325
tty.print(" for JavaThread ");
250-
((JavaThread) handleThread).printThreadIDOn(tty);
326+
((JavaThread) handleThread).printThreadIDOn(tty); // includes "\n"
251327
} else {
252-
tty.print(" for a non-Java Thread");
328+
tty.println(" for a non-Java Thread");
253329
}
254330
} else {
255331
// This must be last
256332
if (Assert.ASSERTS_ENABLED) {
257333
Assert.that(isUnknown(), "Should have unknown location");
258334
}
259-
tty.print("In unknown location");
335+
tty.println("In unknown location");
260336
}
261337
}
262338
}

0 commit comments

Comments
 (0)