Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: Debugger/OnlineDebugger.java


1   // OnlineDebugger.java, created Sat Feb 22 13:35:26 2003 by joewhaley
2   // Copyright (C) 2001-3 John Whaley <jwhaley@alum.mit.edu>
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
4   package Debugger;
5   
6   import java.io.BufferedReader;
7   import java.io.IOException;
8   import java.io.InputStreamReader;
9   import java.util.StringTokenizer;
10  
11  import Allocator.CodeAllocator;
12  import Clazz.jq_Array;
13  import Clazz.jq_Class;
14  import Clazz.jq_CompiledCode;
15  import Clazz.jq_InstanceField;
16  import Clazz.jq_Method;
17  import Clazz.jq_Primitive;
18  import Clazz.jq_Reference;
19  import Compil3r.BytecodeAnalysis.BytecodeVisitor;
20  import Main.TraceFlags;
21  import Main.jq;
22  import Memory.Address;
23  import Memory.CodeAddress;
24  import Memory.HeapAddress;
25  import Memory.StackAddress;
26  import Run_Time.Reflection;
27  import Run_Time.StackCodeWalker;
28  import Run_Time.SystemInterface;
29  import Scheduler.jq_NativeThread;
30  import Util.Assert;
31  import Util.Strings;
32  
33  /**
34   * @author John Whaley <jwhaley@alum.mit.edu>
35   * @version $Id: OnlineDebugger.java,v 1.4 2003/05/12 10:05:16 joewhaley Exp $
36   */
37  public class OnlineDebugger {
38  
39      public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
40  
41      public static boolean debuggerEntryPoint() {
42          if (!jq.RunningNative) {
43              new InternalError().printStackTrace();
44              System.exit(-1);
45          }
46          SystemInterface.debugwriteln(">>> Entering debugger.");
47          StackAddress fp = StackAddress.getBasePointer();
48          CodeAddress ip = (CodeAddress) fp.offset(4).peek();
49          fp = (StackAddress) fp.peek();
50          StackCodeWalker sw = new StackCodeWalker(ip, fp);
51          int frameNum = 0;
52          SystemInterface.debugwriteln("> "+frameNum+":"+sw.toString());
53          //bsh.Interpreter i = null;
54  uphere:
55          for (;;) {
56              System.err.print("db> ");
57              String s = null;
58              try {
59                  s = in.readLine();
60              } catch (IOException _) { }
61              if (s == null) {
62                  SystemInterface.debugwriteln(">>> Exiting debugger.");
63                  return true;
64              }
65              if (s.equals("")) {
66                  continue;
67              }
68              if (s.equals("c")) {
69                  SystemInterface.debugwriteln(">>> Continuing execution.");
70                  return true;
71              }
72              if (s.equals("s")) {
73                  SystemInterface.debugwriteln("Single-step not yet implemented.");
74                  continue;
75              }
76              if (s.equals("u")) {
77                  if (!sw.hasNext()) {
78                      SystemInterface.debugwriteln("Reached top.");
79                      continue;
80                  }
81                  sw.gotoNext(); ++frameNum;
82                  SystemInterface.debugwriteln("> "+frameNum+":"+sw.toString());
83                  continue;
84              }
85              if (s.equals("d")) {
86                  if (frameNum == 0) {
87                      SystemInterface.debugwriteln("Reached top.");
88                      continue;
89                  }
90                  StackCodeWalker sw2 = new StackCodeWalker(ip, fp);
91                  for (;;) {
92                      if (!sw2.hasNext()) {
93                          SystemInterface.debugwriteln("ERROR! Stack is corrupted.");
94                          continue uphere;
95                      }
96                      if (sw2.getFP().peek().difference(sw.getFP()) == 0)
97                          break;
98                      sw2.gotoNext();
99                  }
100                 sw = sw2; --frameNum;
101                 SystemInterface.debugwriteln("> "+frameNum+":"+sw.toString());
102                 continue;
103             }
104             if (s.equals("bt")) {
105                 StackCodeWalker sw2 = new StackCodeWalker(ip, fp);
106                 int counter = 0;
107                 while (sw2.hasNext()) {
108                     if (counter == frameNum) {
109                         SystemInterface.debugwriteln("> "+counter+":"+sw2.toString());
110                         if (sw2.getFP().difference(sw.getFP()) != 0) {
111                             SystemInterface.debugwriteln("ERROR! Stack is corrupted. Expected "+sw+" but found "+sw2);
112                         }
113                     } else {
114                         SystemInterface.debugwriteln("  "+counter+":"+sw2.toString());
115                     }
116                     sw2.gotoNext(); ++counter;
117                 }
118                 continue;
119             }
120             if (s.equals("t")) {
121                 jq_NativeThread.dumpAllThreads();
122                 continue;
123             }
124             if (s.equals("sf")) {
125                 printStackFrame(sw);
126                 continue;
127             }
128             if (s.equals("l")) {
129                 jq_Method m = sw.getMethod();
130                 if (m == null) {
131                     SystemInterface.debugwriteln("Unknown method!");
132                     continue;
133                 }
134                 if (m.getBytecode() == null) {
135                     SystemInterface.debugwriteln("No bytecode for method "+m+"!");
136                     continue;
137                 }
138                 int currentIndex = sw.getBCIndex();
139                 if (currentIndex < 0) currentIndex = 0;
140                 BytecodeLister bl = new BytecodeLister(m, 0, m.getBytecode().length, currentIndex);
141                 bl.forwardTraversal();
142                 continue;
143             }
144             if (s.equals("?")) {
145                 printUsage();
146                 continue;
147             }
148             if (s.startsWith("toString ")) {
149                 s = s.substring(9);
150                 if (s.startsWith("0x") || s.startsWith("0X")) s = s.substring(2);
151                 int k = Integer.parseInt(s, 16);
152                 HeapAddress addr = HeapAddress.address32(k);
153                 Object o = addr.asObject();
154                 SystemInterface.debugwriteln(o.toString());
155                 continue;
156             }
157             if (s.startsWith("dumpObject ")) {
158                 s = s.substring(11);
159                 if (s.startsWith("0x") || s.startsWith("0X")) s = s.substring(2);
160                 int k = Integer.parseInt(s, 16);
161                 dumpObject(k);
162                 continue;
163             }
164             
165             String[] commands;
166             StringTokenizer st = new StringTokenizer(s);
167             int size = st.countTokens();
168             commands = new String[size];
169             for (int j = 0; j < size; ++j) {
170                 commands[j] = st.nextToken();
171             }
172             Assert._assert(!st.hasMoreTokens());
173             int index2 = TraceFlags.setTraceFlag(commands, 0);
174             if (0 != index2) {
175                 continue;
176             }
177             
178             /*
179             if (i == null) i = new bsh.Interpreter();
180             try {
181                 Object result = i.eval(s);
182                 SystemInterface.debugwriteln("Result: "+result);
183             } catch (bsh.EvalError x) {
184                 SystemInterface.debugwriteln("Evaluation error: "+x);
185             }
186             */
187         }
188     }
189 
190     public static void printUsage() {
191         SystemInterface.debugwriteln("c: continue, s: step");
192         SystemInterface.debugwriteln("l: list bytecode");
193         SystemInterface.debugwriteln("dumpObject, toString");
194         SystemInterface.debugwriteln("u: up, d: down, sf: stack frame, bt: back trace, t: thread dump");
195     }
196     
197     public static void dumpObject(int k) {
198         HeapAddress addr = HeapAddress.address32(k);
199         Object o = addr.asObject();
200         dumpObject(o);
201     }
202     
203     public static void dumpObject(Object o) {
204         HeapAddress addr = HeapAddress.addressOf(o);
205         jq_Reference t = jq_Reference.getTypeOf(o);
206         SystemInterface.debugwriteln(addr.stringRep()+" type "+t);
207         if (t.isClassType()) {
208             jq_Class c = (jq_Class) t;
209             jq_InstanceField[] f = c.getInstanceFields();
210             for (int j=0; j<f.length; ++j) {
211                 StringBuffer sb = new StringBuffer();
212                 sb.append(Strings.left(f[j].getName().toString(), 15));
213                 sb.append(':');
214                 if (f[j].getType().isReferenceType()) {
215                     Address addr2 = addr.offset(f[j].getOffset()).peek();
216                     sb.append(addr2.stringRep());
217                 } else {
218                     sb.append(Reflection.getfield(o, f[j]));
219                 }
220                 SystemInterface.debugwriteln(sb.toString());
221             }
222         } else {
223             jq_Array a = (jq_Array) t;
224             int length = Reflection.arraylength(o);
225             for (int j=0; j<length; ++j) {
226                 if (a.getElementType().isReferenceType()) {
227                     SystemInterface.debugwriteln(j+": "+addr.offset(j*HeapAddress.size()).peek().stringRep());
228                 } else if (a.getElementType() == jq_Primitive.FLOAT) {
229                     SystemInterface.debugwriteln(j+": "+Float.intBitsToFloat(addr.offset(j*4).peek4()));
230                 } else if (a.getElementType() == jq_Primitive.DOUBLE) {
231                     SystemInterface.debugwriteln(j+": "+Double.longBitsToDouble(addr.offset(j*8).peek8()));
232                 } else if (a.getElementType().getReferenceSize() == 1) {
233                     SystemInterface.debugwriteln(j+": "+addr.offset(j).peek1());
234                 } else if (a.getElementType().getReferenceSize() == 2) {
235                     SystemInterface.debugwriteln(j+": "+addr.offset(j*2).peek2());
236                 } else if (a.getElementType().getReferenceSize() == 4) {
237                     SystemInterface.debugwriteln(j+": "+addr.offset(j*4).peek4());
238                 } else if (a.getElementType().getReferenceSize() == 8) {
239                     SystemInterface.debugwriteln(j+": "+addr.offset(j*8).peek8());
240                 }
241             }
242         }
243     }
244     
245     public static void printStackFrame(StackCodeWalker sw) {
246         StackAddress my_fp = sw.getFP();
247         if (my_fp.isNull()) {
248             SystemInterface.debugwriteln("Cannot dump this frame!"+Strings.lineSep);
249             return;
250         }
251         CodeAddress my_ip = (CodeAddress) my_fp.offset(4).peek();
252         StackAddress next_fp = (StackAddress) my_fp.peek();
253         if (my_fp.isNull()) {
254             SystemInterface.debugwriteln("Cannot dump this frame!"+Strings.lineSep);
255             return;
256         }
257         jq_CompiledCode cc = CodeAllocator.getCodeContaining(my_ip);
258         jq_Method m = null;
259         if (cc != null) m = cc.getMethod();
260         SystemInterface.debugwriteln("Stack frame for "+cc);
261         if (m != null) {
262             SystemInterface.debugwriteln(((int)m.getMaxLocals())+" locals, "+((int)m.getParamWords())+" param words");
263         }
264         // b0: next->| caller's saved FP  |
265         // ac:       | caller's locals    |
266         //           |        ...         |
267         // 94:       | caller's opstack   |
268         //           |        ...         |
269         // 80:       | pushed params      |
270         //           |        ...         |
271         // 74:       | ret addr in caller |
272         // 70:   my->| callee's FP (b0)   |
273         StackAddress ptr = my_fp;
274         int framesize = 0;
275         if (m != null) framesize = (m.getParamWords()+1)*StackAddress.size();
276         while (ptr.difference(next_fp) <= framesize) {
277             if (ptr.difference(my_fp) == 0) {
278                 SystemInterface.debugwriteln("Callee FP:      "+ptr.stringRep()+" : "+ptr.peek().stringRep());
279             } else if (ptr.difference(next_fp) == StackAddress.size()) {
280                 CodeAddress my_ip2 = (CodeAddress) ptr.peek();
281                 jq_CompiledCode cc2 = CodeAllocator.getCodeContaining(my_ip2);
282                 int code_offset = 0;
283                 if (cc2 != null)
284                     code_offset = my_ip2.difference(cc2.getStart());
285                 SystemInterface.debugwriteln("Caller retaddr: "+ptr.stringRep()+" : "+ptr.peek().stringRep()+"  (offset "+Strings.hex(code_offset)+")");
286             } else if (m != null && ptr.difference(next_fp) > 0) {
287                 int n = m.getParamWords() - ptr.difference(next_fp) / StackAddress.size() + 1;
288                 SystemInterface.debugwriteln(Strings.left("Incoming arg "+n+":", 16)+ptr.stringRep()+" : "+ptr.peek().stringRep());
289             } else if (ptr.difference(my_fp) == StackAddress.size()) {
290                 int code_offset = 0;
291                 if (cc != null)
292                     code_offset = my_ip.difference(cc.getStart());
293                 SystemInterface.debugwriteln("Return address: "+ptr.stringRep()+" : "+ptr.peek().stringRep()+"  (offset "+Strings.hex(code_offset)+")");
294             } else if (next_fp.difference(ptr) == 0) {
295                 SystemInterface.debugwriteln("Caller FP:      "+ptr.stringRep()+" : "+ptr.peek().stringRep());
296             } else if (m != null && next_fp.difference(ptr) <= StackAddress.size()*(m.getMaxLocals()-m.getParamWords())) {
297                 int n = next_fp.difference(ptr) / StackAddress.size() - 1;
298                 SystemInterface.debugwriteln(Strings.left("Local "+n+": ", 16)+ptr.stringRep()+" : "+ptr.peek().stringRep());
299             } else if (m != null && ptr.difference(my_fp) > StackAddress.size()) {
300                 int n = next_fp.difference(ptr) / StackAddress.size() - m.getMaxLocals() + m.getParamWords() - 2;
301                 SystemInterface.debugwriteln(Strings.left("Stack "+n+": ", 16)+ptr.stringRep()+" : "+ptr.peek().stringRep());
302             } else {
303                 SystemInterface.debugwriteln("                "+ptr.stringRep()+" : "+ptr.peek().stringRep());
304             }
305             ptr = (StackAddress) ptr.offset(StackAddress.size());
306         }
307     }
308     
309     public static class BytecodeLister extends BytecodeVisitor {
310         
311         protected int i_loc;
312         protected int i_stop;
313         
314         public BytecodeLister(jq_Method m, int start, int stop, int loc) {
315             super(m);
316             this.i_end = start-1;
317             this.i_start = start;
318             this.i_stop = stop;
319             this.i_loc = loc;
320             this.out = System.err;
321             this.TRACE = true;
322         }
323         public void forwardTraversal() throws VerifyError {
324             for (i_end=-1; ; ) {
325                 i_start = i_end+1;
326                 if (i_start == i_loc) {
327                     out.println("Current location:");
328                 }
329                 if (i_start >= i_stop) break;
330                 this.visitBytecode();
331             }
332         }
333         public String toString() { return Strings.left(method.getName().toString(), 12); }
334     }
335     
336 }