Skip to content

Commit eaefb1a

Browse files
committed
8244669: convert clhsdb "mem" command from javascript to java
Reviewed-by: sspitsyn, kevinw, poonam
1 parent d64820d commit eaefb1a

File tree

3 files changed

+129
-36
lines changed

3 files changed

+129
-36
lines changed

src/jdk.hotspot.agent/doc/clhsdb.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ <h3>Annotated output of CLHSDB help command</h3>
4242
dumpilt -a | id <font color="red">dump inline tree for C2 compilation</font>
4343
dumpreplaydata &lt;address&gt; | -a | &lt;thread_id&gt; [&gt;replay.txt] <font color="red">dump replay data into a file</font>
4444
echo [ true | false ] <font color="red">turn on/off command echo mode</font>
45-
examine [ address/count ] | [ address,address] <font color="red">show contents of memory from given address</font>
45+
examine { address[/count] | address,address } <font color="red">show contents of memory range</font>
4646
field [ type [ name fieldtype isStatic offset address ] ] <font color="red">print info about a field of HotSpot type</font>
4747
findpc address <font color="red">print info about pointer location</font>
4848
findsym name <font color="red">print address of symbol in the executable or shared library</font>
@@ -56,7 +56,7 @@ <h3>Annotated output of CLHSDB help command</h3>
5656
jstack [-v] <font color="red">show Java stack trace of all Java threads. -v is verbose mode</font>
5757
livenmethods <font color="red">show all live nmethods</font>
5858
longConstant [ name [ value ] ] <font color="red">print out hotspot long constant(s)s</font>
59-
mem address [ length ] <font color="red">show contents of memory -- also shows closest ELF/COFF symbol if found</font>
59+
mem [ -v ] { address[/count] | address,address } <font color="red">show contents of memory range. -v adds "findpc" info for addresses</font>
6060
pmap <font color="red">show Solaris pmap-like output</font>
6161
print expression <font color="red">print given Klass*, Method* or arbitrary address</font>
6262
printas type expression <font color="red">print given address as given HotSpot type. eg. print JavaThread &lt;address&gt;</font>

src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java

Lines changed: 114 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,54 @@ Address parseAddress(String addr) {
364364
return VM.getVM().getDebugger().parseAddress(addr);
365365
}
366366

367+
String fillHexString(Address a, int width) {
368+
String s = "0x0";
369+
if (a != null) {
370+
s = a.toString();
371+
}
372+
if (s.length() != width) {
373+
return s.substring(0, 2) + "000000000000000000000".substring(0, width - s.length()) + s.substring(2);
374+
}
375+
return s;
376+
}
377+
378+
class AddressRange {
379+
private Address start;
380+
private Address end;
381+
AddressRange(Address start, Address end) {
382+
this.start = start;
383+
this.end = end;
384+
}
385+
Address getStart() {return start;}
386+
Address getEnd() {return end;}
387+
}
388+
389+
// Parses either address[/count] or address,address into address start/end values
390+
AddressRange parseAddressRange(String arg, int formatSize) {
391+
Pattern args1 = Pattern.compile("^(0x[0-9a-f]+)(/([0-9]*))?$");
392+
Pattern args2 = Pattern.compile("^(0x[0-9a-f]+),(0x[0-9a-f]+)$");
393+
Matcher m1 = args1.matcher(arg);
394+
Matcher m2 = args2.matcher(arg);
395+
Address start = null;
396+
Address end = null;
397+
398+
if (m1.matches()) {
399+
start = VM.getVM().getDebugger().parseAddress(m1.group(1));
400+
int count = 1;
401+
if (m1.group(2) != null) {
402+
count = Integer.parseInt(m1.group(3));
403+
}
404+
end = start.addOffsetTo(count * formatSize);
405+
return new AddressRange(start, end);
406+
} else if (m2.matches()) {
407+
start = VM.getVM().getDebugger().parseAddress(m2.group(1));
408+
end = VM.getVM().getDebugger().parseAddress(m2.group(2));
409+
return new AddressRange(start, end);
410+
} else {
411+
return null;
412+
}
413+
}
414+
367415
private final Command[] commandList = {
368416
new Command("reattach", true) {
369417
public void doit(Tokens t) {
@@ -409,65 +457,40 @@ public void doit(Tokens t) {
409457
}
410458
}
411459
},
412-
new Command("examine", "examine [ address/count ] | [ address,address]", false) {
413-
Pattern args1 = Pattern.compile("^(0x[0-9a-f]+)(/([0-9]*)([a-z]*))?$");
414-
Pattern args2 = Pattern.compile("^(0x[0-9a-f]+),(0x[0-9a-f]+)(/[a-z]*)?$");
415-
416-
String fill(Address a, int width) {
417-
String s = "0x0";
418-
if (a != null) {
419-
s = a.toString();
420-
}
421-
if (s.length() != width) {
422-
return s.substring(0, 2) + "000000000000000000000".substring(0, width - s.length()) + s.substring(2);
423-
}
424-
return s;
425-
}
426-
460+
new Command("examine", "examine { address[/count] | address,address }", false) {
427461
public void doit(Tokens t) {
428462
if (t.countTokens() != 1) {
429463
usage();
430464
} else {
431465
String arg = t.nextToken();
432-
Matcher m1 = args1.matcher(arg);
433-
Matcher m2 = args2.matcher(arg);
434-
Address start = null;
435-
Address end = null;
436466
int formatSize = (int)VM.getVM().getAddressSize();
437-
438-
if (m1.matches()) {
439-
start = VM.getVM().getDebugger().parseAddress(m1.group(1));
440-
int count = 1;
441-
if (m1.group(2) != null) {
442-
count = Integer.parseInt(m1.group(3));
443-
}
444-
end = start.addOffsetTo(count * formatSize);
445-
} else if (m2.matches()) {
446-
start = VM.getVM().getDebugger().parseAddress(m2.group(1));
447-
end = VM.getVM().getDebugger().parseAddress(m2.group(2));
448-
} else {
467+
AddressRange addressRange = parseAddressRange(arg, formatSize);
468+
if (addressRange == null) {
449469
usage();
450470
return;
451471
}
472+
Address start = addressRange.getStart();
473+
Address end = addressRange.getEnd();
474+
452475
int line = 80;
453476
int formatWidth = formatSize * 8 / 4 + 2;
454477

455-
out.print(fill(start, formatWidth));
478+
out.print(fillHexString(start, formatWidth));
456479
out.print(": ");
457480
int width = line - formatWidth - 2;
458481

459482
boolean needsPrintln = true;
460483
while (start != null && start.lessThan(end)) {
461484
Address val = start.getAddressAt(0);
462-
out.print(fill(val, formatWidth));
485+
out.print(fillHexString(val, formatWidth));
463486
needsPrintln = true;
464487
width -= formatWidth;
465488
start = start.addOffsetTo(formatSize);
466489
if (width <= formatWidth) {
467490
out.println();
468491
needsPrintln = false;
469492
if (start.lessThan(end)) {
470-
out.print(fill(start, formatWidth));
493+
out.print(fillHexString(start, formatWidth));
471494
out.print(": ");
472495
width = line - formatWidth - 2;
473496
}
@@ -482,6 +505,63 @@ public void doit(Tokens t) {
482505
}
483506
}
484507
},
508+
new Command("mem", "mem [-v] { address[/count] | address,address }", false) {
509+
public void doit(Tokens t) {
510+
int formatSize = (int)VM.getVM().getAddressSize();
511+
boolean verbose = false;
512+
String arg;
513+
514+
if (t.countTokens() == 2) {
515+
arg = t.nextToken();
516+
if (arg.equals("-v")) {
517+
verbose = true;
518+
} else {
519+
usage();
520+
return;
521+
}
522+
}
523+
if (t.countTokens() != 1) {
524+
usage();
525+
return;
526+
}
527+
528+
arg = t.nextToken();
529+
AddressRange addressRange = parseAddressRange(arg, formatSize);
530+
if (addressRange == null) {
531+
usage();
532+
return;
533+
}
534+
Address start = addressRange.getStart();
535+
Address end = addressRange.getEnd();
536+
537+
if (verbose) {
538+
// Do the equivalent of a findpc on the start address.
539+
PointerLocation loc = PointerFinder.find(start);
540+
loc.printOn(out);
541+
}
542+
543+
int formatWidth = formatSize * 8 / 4 + 2;
544+
while (start != null && start.lessThan(end)) {
545+
out.print(fillHexString(start, formatWidth));
546+
out.print(": ");
547+
Address val = start.getAddressAt(0);
548+
out.print(fillHexString(val, formatWidth));
549+
if (verbose) {
550+
// If we know what this is a pointer to, then print additional information.
551+
PointerLocation loc = PointerFinder.find(val);
552+
if (!loc.isUnknown()) {
553+
out.print(" ");
554+
loc.printOn(out, false, false);
555+
} else {
556+
out.println();
557+
}
558+
} else {
559+
out.println();
560+
}
561+
start = start.addOffsetTo(formatSize);
562+
}
563+
}
564+
},
485565
new Command("dumpreplaydata", "dumpreplaydata { <address > | -a | <thread_id> }", false) {
486566
// This is used to dump replay data from ciInstanceKlass, ciMethodData etc
487567
// default file name is replay.txt, also if java crashes in compiler

test/hotspot/jtreg/serviceability/sa/ClhsdbFindPC.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,19 @@ private static void testFindPC(boolean withXcomp, boolean withCore) throws Excep
191191
methodAddr));
192192
runTest(withCore, cmds, expStrMap);
193193

194+
// Run "mem -v <addr>/30" on a Method*. The first line will look like:
195+
// Address 0x0000152e30403530: Method jdk/test/lib/apps/LingeredApp.steadyState(Ljava/lang/Object;)V@0x0000152e30403530
196+
// Followed by lines displaying the memory contents, including interpretation
197+
// of any contents that are addresses.
198+
cmdStr = "mem -v " + methodAddr + "/30";
199+
cmds = List.of(cmdStr);
200+
expStrMap = new HashMap<>();
201+
expStrMap.put(cmdStr, List.of("Method jdk/test/lib/apps/LingeredApp.steadyState",
202+
methodAddr,
203+
/* The following is from a field in the Method object. */
204+
"In interpreter codelet: method entry point"));
205+
runTest(withCore, cmds, expStrMap);
206+
194207
// Run findpc on a JavaThread*. We can find one in the jstack output.
195208
// The tid for a thread is it's JavaThread*. For example:
196209
// "main" #1 prio=5 tid=0x00000080263398f0 nid=0x277e0 ...

0 commit comments

Comments
 (0)