comparison agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children ba764ed4b6f2
comparison
equal deleted inserted replaced
-1:000000000000 0:a61af66fc99e
1 /*
2 * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 *
23 */
24
25 package sun.jvm.hotspot;
26
27 import java.io.*;
28 import java.math.*;
29 import java.util.*;
30 import java.util.regex.*;
31
32 import sun.jvm.hotspot.types.Type;
33 import sun.jvm.hotspot.types.Field;
34 import sun.jvm.hotspot.HotSpotTypeDataBase;
35 import sun.jvm.hotspot.types.basic.BasicType;
36 import sun.jvm.hotspot.types.CIntegerType;
37 import sun.jvm.hotspot.code.*;
38 import sun.jvm.hotspot.compiler.*;
39 import sun.jvm.hotspot.debugger.*;
40 import sun.jvm.hotspot.interpreter.*;
41 import sun.jvm.hotspot.memory.*;
42 import sun.jvm.hotspot.oops.*;
43 import sun.jvm.hotspot.runtime.*;
44 import sun.jvm.hotspot.utilities.*;
45 import sun.jvm.hotspot.utilities.soql.*;
46 import sun.jvm.hotspot.ui.classbrowser.*;
47 import sun.jvm.hotspot.ui.tree.*;
48 import sun.jvm.hotspot.tools.*;
49 import sun.jvm.hotspot.tools.ObjectHistogram;
50 import sun.jvm.hotspot.tools.StackTrace;
51
52 public class CommandProcessor {
53 public abstract static class DebuggerInterface {
54 public abstract HotSpotAgent getAgent();
55 public abstract boolean isAttached();
56 public abstract void attach(String pid);
57 public abstract void attach(String java, String core);
58 public abstract void detach();
59 public abstract void reattach();
60 }
61
62 static class Tokens {
63 final String input;
64 int i;
65 String[] tokens;
66 int length;
67
68 String[] splitWhitespace(String cmd) {
69 String[] t = cmd.split("\\s");
70 if (t.length == 1 && t[0].length() == 0) {
71 return new String[0];
72 }
73 return t;
74 }
75
76 void add(String s, ArrayList t) {
77 if (s.length() > 0) {
78 t.add(s);
79 }
80 }
81
82 Tokens(String cmd) {
83 input = cmd;
84
85 // check for quoting
86 int quote = cmd.indexOf('"');
87 ArrayList t = new ArrayList();
88 if (quote != -1) {
89 while (cmd.length() > 0) {
90 if (quote != -1) {
91 int endquote = cmd.indexOf('"', quote + 1);
92 if (endquote == -1) {
93 throw new RuntimeException("mismatched quotes: " + input);
94 }
95
96 String before = cmd.substring(0, quote).trim();
97 String quoted = cmd.substring(quote + 1, endquote);
98 cmd = cmd.substring(endquote + 1).trim();
99 if (before.length() > 0) {
100 String[] w = splitWhitespace(before);
101 for (int i = 0; i < w.length; i++) {
102 add(w[i], t);
103 }
104 }
105 add(quoted, t);
106 quote = cmd.indexOf('"');
107 } else {
108 String[] w = splitWhitespace(cmd);
109 for (int i = 0; i < w.length; i++) {
110 add(w[i], t);
111 }
112 cmd = "";
113
114 }
115 }
116 } else {
117 String[] w = splitWhitespace(cmd);
118 for (int i = 0; i < w.length; i++) {
119 add(w[i], t);
120 }
121 }
122 tokens = (String[])t.toArray(new String[0]);
123 i = 0;
124 length = tokens.length;
125
126 //for (int i = 0; i < tokens.length; i++) {
127 // System.out.println("\"" + tokens[i] + "\"");
128 //}
129 }
130
131 String nextToken() {
132 return tokens[i++];
133 }
134 boolean hasMoreTokens() {
135 return i < length;
136 }
137 int countTokens() {
138 return length - i;
139 }
140 void trim(int n) {
141 if (length >= n) {
142 length -= n;
143 } else {
144 throw new IndexOutOfBoundsException(String.valueOf(n));
145 }
146 }
147 String join(String sep) {
148 StringBuffer result = new StringBuffer();
149 for (int w = i; w < length; w++) {
150 result.append(tokens[w]);
151 if (w + 1 < length) {
152 result.append(sep);
153 }
154 }
155 return result.toString();
156 }
157
158 String at(int i) {
159 if (i < 0 || i >= length) {
160 throw new IndexOutOfBoundsException(String.valueOf(i));
161 }
162 return tokens[i];
163 }
164 }
165
166
167 abstract class Command {
168 Command(String n, String u, boolean ok) {
169 name = n;
170 usage = u;
171 okIfDisconnected = ok;
172 }
173
174 Command(String n, boolean ok) {
175 name = n;
176 usage = n;
177 okIfDisconnected = ok;
178 }
179
180 final String name;
181 final String usage;
182 final boolean okIfDisconnected;
183 abstract void doit(Tokens t);
184 void usage() {
185 out.println("Usage: " + usage);
186 }
187
188 void printOopValue(Oop oop) {
189 if (oop != null) {
190 Klass k = oop.getKlass();
191 Symbol s = k.getName();
192 if (s != null) {
193 out.print("Oop for " + s.asString() + " @ ");
194 } else {
195 out.print("Oop @ ");
196 }
197 Oop.printOopAddressOn(oop, out);
198 } else {
199 out.print("null");
200 }
201 }
202
203 void printNode(SimpleTreeNode node) {
204 int count = node.getChildCount();
205 for (int i = 0; i < count; i++) {
206 try {
207 SimpleTreeNode field = node.getChild(i);
208 if (field instanceof OopTreeNodeAdapter) {
209 out.print(field);
210 out.print(" ");
211 printOopValue(((OopTreeNodeAdapter)field).getOop());
212 out.println();
213 } else {
214 out.println(field);
215 }
216 } catch (Exception e) {
217 out.println();
218 out.println("Error: " + e);
219 if (verboseExceptions) {
220 e.printStackTrace(out);
221 }
222 }
223 }
224 }
225 }
226
227 void quote(String s) {
228 if (s.indexOf(" ") == -1) {
229 out.print(s);
230 } else {
231 out.print("\"");
232 out.print(s);
233 out.print("\"");
234 }
235 }
236
237 void dumpType(Type type) {
238 out.print("type ");
239 quote(type.getName());
240 out.print(" ");
241 if (type.getSuperclass() != null) {
242 quote(type.getSuperclass().getName());
243 out.print(" ");
244 } else {
245 out.print("null ");
246 }
247 out.print(type.isOopType());
248 out.print(" ");
249 if (type.isCIntegerType()) {
250 out.print("true ");
251 out.print(((CIntegerType)type).isUnsigned());
252 out.print(" ");
253 } else {
254 out.print("false false ");
255 }
256 out.print(type.getSize());
257 out.println();
258 }
259
260 void dumpFields(Type type) {
261 Iterator i = type.getFields();
262 while (i.hasNext()) {
263 Field f = (Field) i.next();
264 out.print("field ");
265 quote(type.getName());
266 out.print(" ");
267 out.print(f.getName());
268 out.print(" ");
269 quote(f.getType().getName());
270 out.print(" ");
271 out.print(f.isStatic());
272 out.print(" ");
273 if (f.isStatic()) {
274 out.print("0 ");
275 out.print(f.getStaticFieldAddress());
276 } else {
277 out.print(f.getOffset());
278 out.print(" 0x0");
279 }
280 out.println();
281 }
282 }
283
284
285 Address lookup(String symbol) {
286 if (symbol.indexOf("::") != -1) {
287 String[] parts = symbol.split("::");
288 StringBuffer mangled = new StringBuffer("__1c");
289 for (int i = 0; i < parts.length; i++) {
290 int len = parts[i].length();
291 if (len >= 26) {
292 mangled.append((char)('a' + (len / 26)));
293 len = len % 26;
294 }
295 mangled.append((char)('A' + len));
296 mangled.append(parts[i]);
297 }
298 mangled.append("_");
299 symbol = mangled.toString();
300 }
301 return VM.getVM().getDebugger().lookup(null, symbol);
302 }
303
304 Address parseAddress(String addr) {
305 return VM.getVM().getDebugger().parseAddress(addr);
306 }
307
308 private final Command[] commandList = {
309 new Command("reattach", true) {
310 public void doit(Tokens t) {
311 int tokens = t.countTokens();
312 if (tokens != 0) {
313 usage();
314 return;
315 }
316 preAttach();
317 debugger.reattach();
318 postAttach();
319 }
320 },
321 new Command("attach", "attach pid | exec core", true) {
322 public void doit(Tokens t) {
323 int tokens = t.countTokens();
324 if (tokens == 1) {
325 preAttach();
326 debugger.attach(t.nextToken());
327 postAttach();
328 } else if (tokens == 2) {
329 preAttach();
330 debugger.attach(t.nextToken(), t.nextToken());
331 postAttach();
332 } else {
333 usage();
334 }
335 }
336 },
337 new Command("detach", false) {
338 public void doit(Tokens t) {
339 if (t.countTokens() != 0) {
340 usage();
341 } else {
342 debugger.detach();
343 }
344 }
345 },
346 new Command("examine", "examine [ address/count ] | [ address,address]", false) {
347 Pattern args1 = Pattern.compile("^(0x[0-9a-f]+)(/([0-9]*)([a-z]*))?$");
348 Pattern args2 = Pattern.compile("^(0x[0-9a-f]+),(0x[0-9a-f]+)(/[a-z]*)?$");
349
350 String fill(Address a, int width) {
351 String s = "0x0";
352 if (a != null) {
353 s = a.toString();
354 }
355 if (s.length() != width) {
356 return s.substring(0, 2) + "000000000000000000000".substring(0, width - s.length()) + s.substring(2);
357 }
358 return s;
359 }
360
361 public void doit(Tokens t) {
362 if (t.countTokens() != 1) {
363 usage();
364 } else {
365 String arg = t.nextToken();
366 Matcher m1 = args1.matcher(arg);
367 Matcher m2 = args2.matcher(arg);
368 Address start = null;
369 Address end = null;
370 String format = "";
371 int formatSize = (int)VM.getVM().getAddressSize();
372
373 if (m1.matches()) {
374 start = VM.getVM().getDebugger().parseAddress(m1.group(1));
375 int count = 1;
376 if (m1.group(2) != null) {
377 count = Integer.parseInt(m1.group(3));
378 }
379 end = start.addOffsetTo(count * formatSize);
380 } else if (m2.matches()) {
381 start = VM.getVM().getDebugger().parseAddress(m2.group(1));
382 end = VM.getVM().getDebugger().parseAddress(m2.group(2));
383 } else {
384 usage();
385 return;
386 }
387 int line = 80;
388 int formatWidth = formatSize * 8 / 4 + 2;
389
390 out.print(fill(start, formatWidth));
391 out.print(": ");
392 int width = line - formatWidth - 2;
393
394 boolean needsPrintln = true;
395 while (start != null && start.lessThan(end)) {
396 Address val = start.getAddressAt(0);
397 out.print(fill(val, formatWidth));
398 needsPrintln = true;
399 width -= formatWidth;
400 start = start.addOffsetTo(formatSize);
401 if (width <= formatWidth) {
402 out.println();
403 needsPrintln = false;
404 if (start.lessThan(end)) {
405 out.print(fill(start, formatWidth));
406 out.print(": ");
407 width = line - formatWidth - 2;
408 }
409 } else {
410 out.print(" ");
411 width -= 1;
412 }
413 }
414 if (needsPrintln) {
415 out.println();
416 }
417 }
418 }
419 },
420 new Command("findpc", "findpc address", false) {
421 public void doit(Tokens t) {
422 if (t.countTokens() != 1) {
423 usage();
424 } else {
425 Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());
426 PointerLocation loc = PointerFinder.find(a);
427 loc.printOn(out);
428 }
429 }
430 },
431 new Command("flags", "flags [ flag ]", false) {
432 public void doit(Tokens t) {
433 int tokens = t.countTokens();
434 if (tokens != 0 && tokens != 1) {
435 usage();
436 } else {
437 String name = tokens > 0 ? t.nextToken() : null;
438
439 VM.Flag[] flags = VM.getVM().getCommandLineFlags();
440 if (flags == null) {
441 out.println("Command Flag info not available (use 1.4.1_03 or later)!");
442 } else {
443 boolean printed = false;
444 for (int f = 0; f < flags.length; f++) {
445 VM.Flag flag = flags[f];
446 if (name == null || flag.getName().equals(name)) {
447 out.println(flag.getName() + " = " + flag.getValue());
448 printed = true;
449 }
450 }
451 if (name != null && !printed) {
452 out.println("Couldn't find flag: " + name);
453 }
454 }
455 }
456 }
457 },
458 new Command("help", "help [ command ]", true) {
459 public void doit(Tokens t) {
460 int tokens = t.countTokens();
461 Command cmd = null;
462 if (tokens == 1) {
463 cmd = findCommand(t.nextToken());
464 }
465
466 if (cmd != null) {
467 cmd.usage();
468 } else if (tokens == 0) {
469 out.println("Available commands:");
470 Object[] keys = commands.keySet().toArray();
471 Arrays.sort(keys, new Comparator() {
472 public int compare(Object o1, Object o2) {
473 return o1.toString().compareTo(o2.toString());
474 }
475 });
476 for (int i = 0; i < keys.length; i++) {
477 out.print(" ");
478 out.println(((Command)commands.get(keys[i])).usage);
479 }
480 }
481 }
482 },
483 new Command("history", "history", true) {
484 public void doit(Tokens t) {
485 int tokens = t.countTokens();
486 if (tokens != 0 && (tokens != 1 || !t.nextToken().equals("-h"))) {
487 usage();
488 return;
489 }
490 boolean printIndex = tokens == 0;
491 for (int i = 0; i < history.size(); i++) {
492 if (printIndex) out.print(i + " ");
493 out.println(history.get(i));
494 }
495 }
496 },
497 new Command("inspect", "inspect expression", false) {
498 public void doit(Tokens t) {
499 if (t.countTokens() != 1) {
500 usage();
501 } else {
502 Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());
503 SimpleTreeNode node = null;
504 if (VM.getVM().getUniverse().heap().isInReserved(a)) {
505 OopHandle handle = a.addOffsetToAsOopHandle(0);
506 Oop oop = VM.getVM().getObjectHeap().newOop(handle);
507 node = new OopTreeNodeAdapter(oop, null);
508
509 out.println("instance of " + node.getValue() + " @ " + a +
510 " (size = " + oop.getObjectSize() + ")");
511 } else if (VM.getVM().getCodeCache().contains(a)) {
512 CodeBlob blob = VM.getVM().getCodeCache().findBlobUnsafe(a);
513 a = blob.headerBegin();
514 }
515 if (node == null) {
516 Type type = VM.getVM().getTypeDataBase().guessTypeForAddress(a);
517 if (type != null) {
518 out.println("Type is " + type.getName() + " (size of " + type.getSize() + ")");
519 node = new CTypeTreeNodeAdapter(a, type, null);
520 }
521 }
522 if (node != null) {
523 printNode(node);
524 }
525 }
526 }
527 },
528 new Command("jhisto", "jhisto", false) {
529 public void doit(Tokens t) {
530 ObjectHistogram histo = new ObjectHistogram();
531 histo.run(out, err);
532 }
533 },
534 new Command("jstack", "jstack [-v]", false) {
535 public void doit(Tokens t) {
536 boolean verbose = false;
537 if (t.countTokens() > 0 && t.nextToken().equals("-v")) {
538 verbose = true;
539 }
540 StackTrace jstack = new StackTrace(verbose, true);
541 jstack.run(out);
542 }
543 },
544 new Command("print", "print expression", false) {
545 public void doit(Tokens t) {
546 if (t.countTokens() != 1) {
547 usage();
548 } else {
549 Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());
550 HTMLGenerator gen = new HTMLGenerator(false);
551 out.println(gen.genHTML(a));
552 }
553 }
554 },
555 new Command("printas", "printas type expression", false) {
556 public void doit(Tokens t) {
557 if (t.countTokens() != 2) {
558 usage();
559 } else {
560 Type type = agent.getTypeDataBase().lookupType(t.nextToken());
561 Address a = VM.getVM().getDebugger().parseAddress(t.nextToken());
562 CTypeTreeNodeAdapter node = new CTypeTreeNodeAdapter(a, type, null);
563
564 out.println("pointer to " + type + " @ " + a +
565 " (size = " + type.getSize() + ")");
566 printNode(node);
567 }
568 }
569 },
570 new Command("symbol", "symbol name", false) {
571 public void doit(Tokens t) {
572 if (t.countTokens() != 1) {
573 usage();
574 } else {
575 String symbol = t.nextToken();
576 Address a = lookup(symbol);
577 out.println(symbol + " = " + a);
578 }
579 }
580 },
581 new Command("printstatics", "printstatics [ type ]", false) {
582 public void doit(Tokens t) {
583 if (t.countTokens() > 1) {
584 usage();
585 } else {
586 if (t.countTokens() == 0) {
587 out.println("All known static fields");
588 printNode(new CTypeTreeNodeAdapter(agent.getTypeDataBase().getTypes()));
589 } else {
590 Type type = agent.getTypeDataBase().lookupType(t.nextToken());
591 out.println("Static fields of " + type.getName());
592 printNode(new CTypeTreeNodeAdapter(type));
593 }
594 }
595 }
596 },
597 new Command("pmap", "pmap", false) {
598 public void doit(Tokens t) {
599 PMap pmap = new PMap();
600 pmap.run(out, debugger.getAgent().getDebugger());
601 }
602 },
603 new Command("pstack", "pstack [-v]", false) {
604 public void doit(Tokens t) {
605 boolean verbose = false;
606 if (t.countTokens() > 0 && t.nextToken().equals("-v")) {
607 verbose = true;
608 }
609 PStack pstack = new PStack(verbose, true);
610 pstack.run(out, debugger.getAgent().getDebugger());
611 }
612 },
613 new Command("quit", true) {
614 public void doit(Tokens t) {
615 if (t.countTokens() != 0) {
616 usage();
617 } else {
618 debugger.detach();
619 System.exit(0);
620 }
621 }
622 },
623 new Command("echo", "echo [ true | false ]", true) {
624 public void doit(Tokens t) {
625 if (t.countTokens() == 0) {
626 out.println("echo is " + doEcho);
627 } else if (t.countTokens() == 1) {
628 doEcho = Boolean.valueOf(t.nextToken()).booleanValue();
629 } else {
630 usage();
631 }
632 }
633 },
634 new Command("versioncheck", "versioncheck [ true | false ]", true) {
635 public void doit(Tokens t) {
636 if (t.countTokens() == 0) {
637 out.println("versioncheck is " +
638 (System.getProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck") == null));
639 } else if (t.countTokens() == 1) {
640 if (Boolean.valueOf(t.nextToken()).booleanValue()) {
641 System.setProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck", null);
642 } else {
643 System.setProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck", "true");
644 }
645 } else {
646 usage();
647 }
648 }
649 },
650 new Command("scanoops", "scanoops start end [ type ]", false) {
651 public void doit(Tokens t) {
652 if (t.countTokens() != 2 && t.countTokens() != 3) {
653 usage();
654 } else {
655 long stride = VM.getVM().getAddressSize();
656 Address base = VM.getVM().getDebugger().parseAddress(t.nextToken());
657 Address end = VM.getVM().getDebugger().parseAddress(t.nextToken());
658 Klass klass = null;
659 if (t.countTokens() == 1) {
660 klass = SystemDictionaryHelper.findInstanceKlass(t.nextToken());
661 }
662 while (base != null && base.lessThan(end)) {
663 long step = stride;
664 OopHandle handle = base.addOffsetToAsOopHandle(0);
665 if (RobustOopDeterminator.oopLooksValid(handle)) {
666 try {
667 Oop oop = VM.getVM().getObjectHeap().newOop(handle);
668 if (klass == null || oop.getKlass().isSubtypeOf(klass))
669 out.println(handle.toString() + " " + oop.getKlass().getName().asString());
670 step = oop.getObjectSize();
671 } catch (UnknownOopException ex) {
672 // ok
673 } catch (RuntimeException ex) {
674 ex.printStackTrace();
675 }
676 }
677 base = base.addOffsetTo(step);
678 }
679 }
680 }
681 },
682 new Command("field", "field [ type [ name fieldtype isStatic offset address ] ]", true) {
683 public void doit(Tokens t) {
684 if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 6) {
685 usage();
686 return;
687 }
688 if (t.countTokens() == 1) {
689 Type type = agent.getTypeDataBase().lookupType(t.nextToken());
690 dumpFields(type);
691 } else if (t.countTokens() == 0) {
692 Iterator i = agent.getTypeDataBase().getTypes();
693 while (i.hasNext()) {
694 dumpFields((Type)i.next());
695 }
696 } else {
697 BasicType containingType = (BasicType)agent.getTypeDataBase().lookupType(t.nextToken());
698
699 String fieldName = t.nextToken();
700
701 // The field's Type must already be in the database -- no exceptions
702 Type fieldType = agent.getTypeDataBase().lookupType(t.nextToken());
703
704 boolean isStatic = Boolean.valueOf(t.nextToken()).booleanValue();
705 long offset = Long.parseLong(t.nextToken());
706 Address staticAddress = parseAddress(t.nextToken());
707 if (isStatic && staticAddress == null) {
708 staticAddress = lookup(containingType.getName() + "::" + fieldName);
709 }
710
711 // check to see if the field already exists
712 Iterator i = containingType.getFields();
713 while (i.hasNext()) {
714 Field f = (Field) i.next();
715 if (f.getName().equals(fieldName)) {
716 if (f.isStatic() != isStatic) {
717 throw new RuntimeException("static/nonstatic mismatch: " + t.input);
718 }
719 if (!isStatic) {
720 if (f.getOffset() != offset) {
721 throw new RuntimeException("bad redefinition of field offset: " + t.input);
722 }
723 } else {
724 if (!f.getStaticFieldAddress().equals(staticAddress)) {
725 throw new RuntimeException("bad redefinition of field location: " + t.input);
726 }
727 }
728 if (f.getType() != fieldType) {
729 throw new RuntimeException("bad redefinition of field type: " + t.input);
730 }
731 return;
732 }
733 }
734
735 // Create field by type
736 HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase();
737 db.createField(containingType,
738 fieldName, fieldType,
739 isStatic,
740 offset,
741 staticAddress);
742
743 }
744 }
745
746 },
747 new Command("tokenize", "tokenize ...", true) {
748 public void doit(Tokens t) {
749 while (t.hasMoreTokens()) {
750 out.println("\"" + t.nextToken() + "\"");
751 }
752 }
753 },
754 new Command("type", "type [ type [ name super isOop isInteger isUnsigned size ] ]", true) {
755 public void doit(Tokens t) {
756 if (t.countTokens() != 1 && t.countTokens() != 0 && t.countTokens() != 6) {
757 usage();
758 return;
759 }
760 if (t.countTokens() == 6) {
761 String typeName = t.nextToken();
762 String superclassName = t.nextToken();
763 if (superclassName.equals("null")) {
764 superclassName = null;
765 }
766 boolean isOop = Boolean.valueOf(t.nextToken()).booleanValue();
767 boolean isInteger = Boolean.valueOf(t.nextToken()).booleanValue();
768 boolean isUnsigned = Boolean.valueOf(t.nextToken()).booleanValue();
769 long size = Long.parseLong(t.nextToken());
770
771 BasicType type = null;
772 try {
773 type = (BasicType)agent.getTypeDataBase().lookupType(typeName);
774 } catch (RuntimeException e) {
775 }
776 if (type != null) {
777 if (type.isOopType() != isOop) {
778 throw new RuntimeException("oop mismatch in type definition: " + t.input);
779 }
780 if (type.isCIntegerType() != isInteger) {
781 throw new RuntimeException("integer type mismatch in type definition: " + t.input);
782 }
783 if (type.isCIntegerType() && (((CIntegerType)type).isUnsigned()) != isUnsigned) {
784 throw new RuntimeException("unsigned mismatch in type definition: " + t.input);
785 }
786 if (type.getSuperclass() == null) {
787 if (superclassName != null) {
788 if (type.getSize() == -1) {
789 type.setSuperclass(agent.getTypeDataBase().lookupType(superclassName));
790 } else {
791 throw new RuntimeException("unexpected superclass in type definition: " + t.input);
792 }
793 }
794 } else {
795 if (superclassName == null) {
796 throw new RuntimeException("missing superclass in type definition: " + t.input);
797 }
798 if (!type.getSuperclass().getName().equals(superclassName)) {
799 throw new RuntimeException("incorrect superclass in type definition: " + t.input);
800 }
801 }
802 if (type.getSize() != size) {
803 if (type.getSize() == -1) {
804 type.setSize(size);
805 }
806 throw new RuntimeException("size mismatch in type definition: " + t.input);
807 }
808 return;
809 }
810
811 // Create type
812 HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase();
813 db.createType(typeName, superclassName, isOop, isInteger, isUnsigned, size);
814 } else if (t.countTokens() == 1) {
815 Type type = agent.getTypeDataBase().lookupType(t.nextToken());
816 dumpType(type);
817 } else {
818 Iterator i = agent.getTypeDataBase().getTypes();
819 while (i.hasNext()) {
820 dumpType((Type)i.next());
821 }
822 }
823 }
824
825 },
826 new Command("source", "source filename", true) {
827 public void doit(Tokens t) {
828 if (t.countTokens() != 1) {
829 usage();
830 return;
831 }
832 String file = t.nextToken();
833 BufferedReader savedInput = in;
834 try {
835 BufferedReader input = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
836 in = input;
837 run(false);
838 } catch (Exception e) {
839 out.println("Error: " + e);
840 if (verboseExceptions) {
841 e.printStackTrace(out);
842 }
843 } finally {
844 in = savedInput;
845 }
846
847 }
848 },
849 new Command("search", "search [ heap | codecache | threads ] value", false) {
850 public void doit(Tokens t) {
851 if (t.countTokens() != 2) {
852 usage();
853 } else {
854 String type = t.nextToken();
855 final Address value = VM.getVM().getDebugger().parseAddress(t.nextToken());
856 final long stride = VM.getVM().getAddressSize();
857 if (type.equals("threads")) {
858 Threads threads = VM.getVM().getThreads();
859 for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) {
860 Address base = thread.getBaseOfStackPointer();
861 Address end = thread.getLastJavaSP();
862 if (end == null) continue;
863 if (end.lessThan(base)) {
864 Address tmp = base;
865 base = end;
866 end = tmp;
867 }
868 out.println("Searching " + base + " " + end);
869 while (base != null && base.lessThan(end)) {
870 Address val = base.getAddressAt(0);
871 if (AddressOps.equal(val, value)) {
872 out.println(base);
873 }
874 base = base.addOffsetTo(stride);
875 }
876 }
877 } else if (type.equals("heap")) {
878 RawHeapVisitor iterator = new RawHeapVisitor() {
879 public void prologue(long used) {
880 }
881
882 public void visitAddress(Address addr) {
883 Address val = addr.getAddressAt(0);
884 if (AddressOps.equal(val, value)) {
885 out.println("found at " + addr);
886 }
887 }
888
889 public void epilogue() {
890 }
891 };
892 VM.getVM().getObjectHeap().iterateRaw(iterator);
893 } else if (type.equals("codecache")) {
894 CodeCacheVisitor v = new CodeCacheVisitor() {
895 public void prologue(Address start, Address end) {
896 }
897 public void visit(CodeBlob blob) {
898 boolean printed = false;
899 Address base = blob.getAddress();
900 Address end = base.addOffsetTo(blob.getSize());
901 while (base != null && base.lessThan(end)) {
902 Address val = base.getAddressAt(0);
903 if (AddressOps.equal(val, value)) {
904 if (!printed) {
905 printed = true;
906 blob.printOn(out);
907 }
908 out.println("found at " + base + "\n");
909 }
910 base = base.addOffsetTo(stride);
911 }
912 }
913 public void epilogue() {
914 }
915
916
917 };
918 VM.getVM().getCodeCache().iterate(v);
919
920 }
921 }
922 }
923 },
924 new Command("where", "where { -a | id }", false) {
925 public void doit(Tokens t) {
926 if (t.countTokens() != 1) {
927 usage();
928 } else {
929 String name = t.nextToken();
930 Threads threads = VM.getVM().getThreads();
931 boolean all = name.equals("-a");
932 for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) {
933 StringWriter sw = new StringWriter();
934 ByteArrayOutputStream bos = new ByteArrayOutputStream();
935 thread.printThreadIDOn(new PrintStream(bos));
936 if (all || bos.toString().equals(name)) {
937 HTMLGenerator gen = new HTMLGenerator(false);
938 out.println(gen.genHTMLForJavaStackTrace(thread));
939 if (!all) return;
940 }
941 }
942 if (!all) out.println("Couldn't find thread " + name);
943 }
944 }
945 },
946
947 new Command("threads", false) {
948 public void doit(Tokens t) {
949 if (t.countTokens() != 0) {
950 usage();
951 } else {
952 Threads threads = VM.getVM().getThreads();
953 for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) {
954 thread.printThreadIDOn(out);
955 out.println(" " + thread.getThreadName());
956 }
957 }
958 }
959 },
960
961 new Command("livenmethods", false) {
962 public void doit(Tokens t) {
963 if (t.countTokens() != 0) {
964 usage();
965 } else {
966 ArrayList nmethods = new ArrayList();
967 Threads threads = VM.getVM().getThreads();
968 HTMLGenerator gen = new HTMLGenerator(false);
969 for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) {
970 try {
971 for (JavaVFrame vf = thread.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) {
972 if (vf instanceof CompiledVFrame) {
973 NMethod c = ((CompiledVFrame)vf).getCode();
974 if (!nmethods.contains(c)) {
975 nmethods.add(c);
976 out.println(gen.genHTML(c));
977 }
978 }
979 }
980 } catch (Exception e) {
981 e.printStackTrace();
982 }
983 }
984 }
985 }
986 },
987 new Command("universe", false) {
988 public void doit(Tokens t) {
989 if (t.countTokens() != 0) {
990 usage();
991 } else {
992 Universe u = VM.getVM().getUniverse();
993 out.println("Heap Parameters:");
994 u.heap().printOn(out);
995 }
996 }
997 },
998 new Command("verbose", "verbose true | false", true) {
999 public void doit(Tokens t) {
1000 if (t.countTokens() != 1) {
1001 usage();
1002 } else {
1003 verboseExceptions = Boolean.valueOf(t.nextToken()).booleanValue();
1004 }
1005 }
1006 },
1007 new Command("assert", "assert true | false", true) {
1008 public void doit(Tokens t) {
1009 if (t.countTokens() != 1) {
1010 usage();
1011 } else {
1012 Assert.ASSERTS_ENABLED = Boolean.valueOf(t.nextToken()).booleanValue();
1013 }
1014 }
1015 },
1016 };
1017
1018 private boolean verboseExceptions = false;
1019 private ArrayList history = new ArrayList();
1020 private HashMap commands = new HashMap();
1021 private boolean doEcho = false;
1022
1023 private Command findCommand(String key) {
1024 return (Command)commands.get(key);
1025 }
1026
1027 public void printPrompt() {
1028 out.print("hsdb> ");
1029 }
1030
1031 private DebuggerInterface debugger;
1032 private HotSpotAgent agent;
1033 private JSJavaScriptEngine jsengine;
1034 private BufferedReader in;
1035 private PrintStream out;
1036 private PrintStream err;
1037
1038 // called before debuggee attach
1039 private void preAttach() {
1040 // nothing for now..
1041 }
1042
1043 // called after debuggee attach
1044 private void postAttach() {
1045 // create JavaScript engine and start it
1046 jsengine = new JSJavaScriptEngine() {
1047 private ObjectReader reader = new ObjectReader();
1048 private JSJavaFactory factory = new JSJavaFactoryImpl();
1049 public ObjectReader getObjectReader() {
1050 return reader;
1051 }
1052 public JSJavaFactory getJSJavaFactory() {
1053 return factory;
1054 }
1055 protected void quit() {
1056 debugger.detach();
1057 System.exit(0);
1058 }
1059 protected BufferedReader getInputReader() {
1060 return in;
1061 }
1062 protected PrintStream getOutputStream() {
1063 return out;
1064 }
1065 protected PrintStream getErrorStream() {
1066 return err;
1067 }
1068 };
1069 try {
1070 jsengine.defineFunction(this,
1071 this.getClass().getMethod("registerCommand",
1072 new Class[] {
1073 String.class, String.class, String.class
1074 }));
1075 } catch (NoSuchMethodException exp) {
1076 // should not happen, see below...!!
1077 exp.printStackTrace();
1078 }
1079 jsengine.start();
1080 }
1081
1082 public void registerCommand(String cmd, String usage, final String func) {
1083 commands.put(cmd, new Command(cmd, usage, false) {
1084 public void doit(Tokens t) {
1085 final int len = t.countTokens();
1086 Object[] args = new Object[len];
1087 for (int i = 0; i < len; i++) {
1088 args[i] = t.nextToken();
1089 }
1090 jsengine.call(func, args);
1091 }
1092 });
1093 }
1094
1095 public void setOutput(PrintStream o) {
1096 out = o;
1097 }
1098
1099 public void setErr(PrintStream e) {
1100 err = e;
1101 }
1102
1103 public CommandProcessor(DebuggerInterface debugger, BufferedReader in, PrintStream out, PrintStream err) {
1104 this.debugger = debugger;
1105 this.agent = debugger.getAgent();
1106 this.in = in;
1107 this.out = out;
1108 this.err = err;
1109 for (int i = 0; i < commandList.length; i++) {
1110 Command c = commandList[i];
1111 commands.put(c.name, c);
1112 }
1113 if (debugger.isAttached()) {
1114 postAttach();
1115 }
1116 }
1117
1118
1119 public void run(boolean prompt) {
1120 // Process interactive commands.
1121 while (true) {
1122 if (prompt) printPrompt();
1123 String ln = null;
1124 try {
1125 ln = in.readLine();
1126 } catch (IOException e) {
1127 }
1128 if (ln == null) {
1129 if (prompt) err.println("Input stream closed.");
1130 return;
1131 }
1132
1133 executeCommand(ln);
1134 }
1135 }
1136
1137 static Pattern historyPattern = Pattern.compile("((!\\*)|(!\\$)|(!!-?)|(!-?[0-9][0-9]*))");
1138
1139 public void executeCommand(String ln) {
1140 if (ln.indexOf('!') != -1) {
1141 int size = history.size();
1142 if (size == 0) {
1143 ln = "";
1144 err.println("History is empty");
1145 } else {
1146 StringBuffer result = new StringBuffer();
1147 Matcher m = historyPattern.matcher(ln);
1148 int start = 0;
1149 while (m.find()) {
1150 if (m.start() > start) {
1151 result.append(ln.substring(start, m.start() - start));
1152 }
1153 start = m.end();
1154
1155 String cmd = m.group();
1156 if (cmd.equals("!!")) {
1157 result.append((String)history.get(history.size() - 1));
1158 } else if (cmd.equals("!!-")) {
1159 Tokens item = new Tokens((String)history.get(history.size() - 1));
1160 item.trim(1);
1161 result.append(item.join(" "));
1162 } else if (cmd.equals("!*")) {
1163 Tokens item = new Tokens((String)history.get(history.size() - 1));
1164 item.nextToken();
1165 result.append(item.join(" "));
1166 } else if (cmd.equals("!$")) {
1167 Tokens item = new Tokens((String)history.get(history.size() - 1));
1168 result.append(item.at(item.countTokens() - 1));
1169 } else {
1170 String tail = cmd.substring(1);
1171 int index = Integer.parseInt(tail);
1172 if (index < 0) {
1173 index = history.size() + index;
1174 }
1175 if (index > size) {
1176 err.println("No such history item");
1177 } else {
1178 result.append((String)history.get(index));
1179 }
1180 }
1181 }
1182 if (result.length() == 0) {
1183 err.println("malformed history reference");
1184 ln = "";
1185 } else {
1186 if (start < ln.length()) {
1187 result.append(ln.substring(start));
1188 }
1189 ln = result.toString();
1190 if (!doEcho) {
1191 out.println(ln);
1192 }
1193 }
1194 }
1195 }
1196
1197 if (doEcho) {
1198 out.println("+ " + ln);
1199 }
1200
1201 PrintStream redirect = null;
1202 Tokens t = new Tokens(ln);
1203 if (t.hasMoreTokens()) {
1204 boolean error = false;
1205 history.add(ln);
1206 int len = t.countTokens();
1207 if (len > 2) {
1208 String r = t.at(len - 2);
1209 if (r.equals(">") || r.equals(">>")) {
1210 boolean append = r.length() == 2;
1211 String file = t.at(len - 1);
1212 try {
1213 redirect = new PrintStream(new BufferedOutputStream(new FileOutputStream(file, append)));
1214 t.trim(2);
1215 } catch (Exception e) {
1216 out.println("Error: " + e);
1217 if (verboseExceptions) {
1218 e.printStackTrace(out);
1219 }
1220 error = true;
1221 }
1222 }
1223 }
1224 if (!error) {
1225 PrintStream savedout = out;
1226 if (redirect != null) {
1227 out = redirect;
1228 }
1229 try {
1230 executeCommand(t);
1231 } catch (Exception e) {
1232 err.println("Error: " + e);
1233 if (verboseExceptions) {
1234 e.printStackTrace(err);
1235 }
1236 } finally {
1237 if (redirect != null) {
1238 out = savedout;
1239 redirect.close();
1240 }
1241 }
1242 }
1243 }
1244 }
1245
1246 void executeCommand(Tokens args) {
1247 String cmd = args.nextToken();
1248
1249 Command doit = findCommand(cmd);
1250
1251 /*
1252 * Check for an unknown command
1253 */
1254 if (doit == null) {
1255 out.println("Unrecognized command. Try help...");
1256 } else if (!debugger.isAttached() && !doit.okIfDisconnected) {
1257 out.println("Command not valid until the attached to a VM");
1258 } else {
1259 try {
1260 doit.doit(args);
1261 } catch (Exception e) {
1262 out.println("Error: " + e);
1263 if (verboseExceptions) {
1264 e.printStackTrace(out);
1265 }
1266 }
1267 }
1268 }
1269 }