Skip to content

Commit

Permalink
8244669: convert clhsdb "mem" command from javascript to java
Browse files Browse the repository at this point in the history
Reviewed-by: sspitsyn, kevinw, poonam
  • Loading branch information
plummercj committed Dec 22, 2021
1 parent d64820d commit eaefb1a
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 36 deletions.
4 changes: 2 additions & 2 deletions src/jdk.hotspot.agent/doc/clhsdb.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ <h3>Annotated output of CLHSDB help command</h3>
dumpilt -a | id <font color="red">dump inline tree for C2 compilation</font>
dumpreplaydata &lt;address&gt; | -a | &lt;thread_id&gt; [&gt;replay.txt] <font color="red">dump replay data into a file</font>
echo [ true | false ] <font color="red">turn on/off command echo mode</font>
examine [ address/count ] | [ address,address] <font color="red">show contents of memory from given address</font>
examine { address[/count] | address,address } <font color="red">show contents of memory range</font>
field [ type [ name fieldtype isStatic offset address ] ] <font color="red">print info about a field of HotSpot type</font>
findpc address <font color="red">print info about pointer location</font>
findsym name <font color="red">print address of symbol in the executable or shared library</font>
Expand All @@ -56,7 +56,7 @@ <h3>Annotated output of CLHSDB help command</h3>
jstack [-v] <font color="red">show Java stack trace of all Java threads. -v is verbose mode</font>
livenmethods <font color="red">show all live nmethods</font>
longConstant [ name [ value ] ] <font color="red">print out hotspot long constant(s)s</font>
mem address [ length ] <font color="red">show contents of memory -- also shows closest ELF/COFF symbol if found</font>
mem [ -v ] { address[/count] | address,address } <font color="red">show contents of memory range. -v adds "findpc" info for addresses</font>
pmap <font color="red">show Solaris pmap-like output</font>
print expression <font color="red">print given Klass*, Method* or arbitrary address</font>
printas type expression <font color="red">print given address as given HotSpot type. eg. print JavaThread &lt;address&gt;</font>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,54 @@ Address parseAddress(String addr) {
return VM.getVM().getDebugger().parseAddress(addr);
}

String fillHexString(Address a, int width) {
String s = "0x0";
if (a != null) {
s = a.toString();
}
if (s.length() != width) {
return s.substring(0, 2) + "000000000000000000000".substring(0, width - s.length()) + s.substring(2);
}
return s;
}

class AddressRange {
private Address start;
private Address end;
AddressRange(Address start, Address end) {
this.start = start;
this.end = end;
}
Address getStart() {return start;}
Address getEnd() {return end;}
}

// Parses either address[/count] or address,address into address start/end values
AddressRange parseAddressRange(String arg, int formatSize) {
Pattern args1 = Pattern.compile("^(0x[0-9a-f]+)(/([0-9]*))?$");
Pattern args2 = Pattern.compile("^(0x[0-9a-f]+),(0x[0-9a-f]+)$");
Matcher m1 = args1.matcher(arg);
Matcher m2 = args2.matcher(arg);
Address start = null;
Address end = null;

if (m1.matches()) {
start = VM.getVM().getDebugger().parseAddress(m1.group(1));
int count = 1;
if (m1.group(2) != null) {
count = Integer.parseInt(m1.group(3));
}
end = start.addOffsetTo(count * formatSize);
return new AddressRange(start, end);
} else if (m2.matches()) {
start = VM.getVM().getDebugger().parseAddress(m2.group(1));
end = VM.getVM().getDebugger().parseAddress(m2.group(2));
return new AddressRange(start, end);
} else {
return null;
}
}

private final Command[] commandList = {
new Command("reattach", true) {
public void doit(Tokens t) {
Expand Down Expand Up @@ -409,65 +457,40 @@ public void doit(Tokens t) {
}
}
},
new Command("examine", "examine [ address/count ] | [ address,address]", false) {
Pattern args1 = Pattern.compile("^(0x[0-9a-f]+)(/([0-9]*)([a-z]*))?$");
Pattern args2 = Pattern.compile("^(0x[0-9a-f]+),(0x[0-9a-f]+)(/[a-z]*)?$");

String fill(Address a, int width) {
String s = "0x0";
if (a != null) {
s = a.toString();
}
if (s.length() != width) {
return s.substring(0, 2) + "000000000000000000000".substring(0, width - s.length()) + s.substring(2);
}
return s;
}

new Command("examine", "examine { address[/count] | address,address }", false) {
public void doit(Tokens t) {
if (t.countTokens() != 1) {
usage();
} else {
String arg = t.nextToken();
Matcher m1 = args1.matcher(arg);
Matcher m2 = args2.matcher(arg);
Address start = null;
Address end = null;
int formatSize = (int)VM.getVM().getAddressSize();

if (m1.matches()) {
start = VM.getVM().getDebugger().parseAddress(m1.group(1));
int count = 1;
if (m1.group(2) != null) {
count = Integer.parseInt(m1.group(3));
}
end = start.addOffsetTo(count * formatSize);
} else if (m2.matches()) {
start = VM.getVM().getDebugger().parseAddress(m2.group(1));
end = VM.getVM().getDebugger().parseAddress(m2.group(2));
} else {
AddressRange addressRange = parseAddressRange(arg, formatSize);
if (addressRange == null) {
usage();
return;
}
Address start = addressRange.getStart();
Address end = addressRange.getEnd();

int line = 80;
int formatWidth = formatSize * 8 / 4 + 2;

out.print(fill(start, formatWidth));
out.print(fillHexString(start, formatWidth));
out.print(": ");
int width = line - formatWidth - 2;

boolean needsPrintln = true;
while (start != null && start.lessThan(end)) {
Address val = start.getAddressAt(0);
out.print(fill(val, formatWidth));
out.print(fillHexString(val, formatWidth));
needsPrintln = true;
width -= formatWidth;
start = start.addOffsetTo(formatSize);
if (width <= formatWidth) {
out.println();
needsPrintln = false;
if (start.lessThan(end)) {
out.print(fill(start, formatWidth));
out.print(fillHexString(start, formatWidth));
out.print(": ");
width = line - formatWidth - 2;
}
Expand All @@ -482,6 +505,63 @@ public void doit(Tokens t) {
}
}
},
new Command("mem", "mem [-v] { address[/count] | address,address }", false) {
public void doit(Tokens t) {
int formatSize = (int)VM.getVM().getAddressSize();
boolean verbose = false;
String arg;

if (t.countTokens() == 2) {
arg = t.nextToken();
if (arg.equals("-v")) {
verbose = true;
} else {
usage();
return;
}
}
if (t.countTokens() != 1) {
usage();
return;
}

arg = t.nextToken();
AddressRange addressRange = parseAddressRange(arg, formatSize);
if (addressRange == null) {
usage();
return;
}
Address start = addressRange.getStart();
Address end = addressRange.getEnd();

if (verbose) {
// Do the equivalent of a findpc on the start address.
PointerLocation loc = PointerFinder.find(start);
loc.printOn(out);
}

int formatWidth = formatSize * 8 / 4 + 2;
while (start != null && start.lessThan(end)) {
out.print(fillHexString(start, formatWidth));
out.print(": ");
Address val = start.getAddressAt(0);
out.print(fillHexString(val, formatWidth));
if (verbose) {
// If we know what this is a pointer to, then print additional information.
PointerLocation loc = PointerFinder.find(val);
if (!loc.isUnknown()) {
out.print(" ");
loc.printOn(out, false, false);
} else {
out.println();
}
} else {
out.println();
}
start = start.addOffsetTo(formatSize);
}
}
},
new Command("dumpreplaydata", "dumpreplaydata { <address > | -a | <thread_id> }", false) {
// This is used to dump replay data from ciInstanceKlass, ciMethodData etc
// default file name is replay.txt, also if java crashes in compiler
Expand Down
13 changes: 13 additions & 0 deletions test/hotspot/jtreg/serviceability/sa/ClhsdbFindPC.java
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,19 @@ private static void testFindPC(boolean withXcomp, boolean withCore) throws Excep
methodAddr));
runTest(withCore, cmds, expStrMap);

// Run "mem -v <addr>/30" on a Method*. The first line will look like:
// Address 0x0000152e30403530: Method jdk/test/lib/apps/LingeredApp.steadyState(Ljava/lang/Object;)V@0x0000152e30403530
// Followed by lines displaying the memory contents, including interpretation
// of any contents that are addresses.
cmdStr = "mem -v " + methodAddr + "/30";
cmds = List.of(cmdStr);
expStrMap = new HashMap<>();
expStrMap.put(cmdStr, List.of("Method jdk/test/lib/apps/LingeredApp.steadyState",
methodAddr,
/* The following is from a field in the Method object. */
"In interpreter codelet: method entry point"));
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 ...
Expand Down

1 comment on commit eaefb1a

@openjdk-notifier
Copy link

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.