View Javadoc

1   // StackCodeWalker.java, created Thu Sep 26 22:01:42 2002 by laudney
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 joeq.Runtime;
5   
6   import java.util.Iterator;
7   import java.util.NoSuchElementException;
8   import joeq.Allocator.CodeAllocator;
9   import joeq.Class.jq_CompiledCode;
10  import joeq.Class.jq_Method;
11  import joeq.Memory.CodeAddress;
12  import joeq.Memory.StackAddress;
13  import joeq.UTF.Utf8;
14  import jwutil.strings.Strings;
15  
16  /***
17   * @author  John Whaley <jwhaley@alum.mit.edu>
18   * @version $Id: StackCodeWalker.java 1941 2004-09-30 03:37:06Z joewhaley $
19   */
20  public class StackCodeWalker implements Iterator {
21  
22      public static /*final*/ boolean TRACE = false;
23  
24      CodeAddress ip;
25      StackAddress fp;
26  
27      public CodeAddress getIP() {
28          return ip;
29      }
30  
31      public StackAddress getFP() {
32          return fp;
33      }
34  
35      public jq_CompiledCode getCode() {
36          return CodeAllocator.getCodeContaining(ip);
37      }
38  
39      public jq_Method getMethod() {
40          jq_CompiledCode cc = this.getCode();
41          if (cc == null) return null;
42          return cc.getMethod();
43      }
44      
45      public int getCodeOffset() {
46          jq_CompiledCode cc = this.getCode();
47          if (cc == null) return 0;
48          CodeAddress ip = this.getIP();
49          int code_offset = ip.difference(cc.getStart());
50          return code_offset;
51      }
52      
53      public Utf8 getSourceFile() {
54          jq_Method m = getMethod();
55          if (m == null) return null;
56          Utf8 sourcefile = m.getDeclaringClass().getSourceFile();
57          return sourcefile;
58      }
59      public int getBCIndex() {
60          jq_CompiledCode cc = this.getCode();
61          if (cc == null) return -1;
62          int bc_index = cc.getBytecodeIndex(ip);
63          return bc_index;
64      }
65      
66      public int getLineNum() {
67          jq_Method m = getMethod();
68          if (m == null) return -1;
69          int bc_index = getBCIndex();
70          int line_num = m.getLineNumber(bc_index);
71          return line_num;
72      }
73      
74      public StackCodeWalker(CodeAddress ip, StackAddress fp) {
75          this.ip = ip;
76          this.fp = fp;
77          if (TRACE) SystemInterface.debugwriteln("StackCodeWalker init: fp=" + fp.stringRep() + " ip=" + ip.stringRep() + " " + getCode());
78      }
79  
80      public void gotoNext() throws NoSuchElementException {
81          if (fp.isNull()) throw new NoSuchElementException();
82          ip = (CodeAddress) fp.offset(4).peek();
83          fp = (StackAddress) fp.peek();
84          if (TRACE) SystemInterface.debugwriteln("StackCodeWalker next: fp=" + fp.stringRep() + " ip=" + ip.stringRep() + " " + getCode());
85      }
86  
87      public boolean hasNext() {
88          if (fp.isNull()) return false;
89          CodeAddress addr = (CodeAddress) fp.offset(4).peek();
90          if (TRACE) SystemInterface.debugwriteln("StackCodeWalker hasnext: next ip=" + addr.stringRep() + " " + CodeAllocator.getCodeContaining(addr));
91          return true;
92      }
93  
94      public Object next() throws NoSuchElementException {
95          gotoNext();
96          return new CodeAllocator.InstructionPointer(ip);
97      }
98  
99      public void remove() throws UnsupportedOperationException {
100         throw new UnsupportedOperationException();
101     }
102 
103     public String toString() {
104         jq_CompiledCode cc = this.getCode();
105         CodeAddress ip = this.getIP();
106         String s;
107         if (cc != null) {
108             jq_Method m = cc.getMethod();
109             int code_offset = ip.difference(cc.getStart());
110             if (m != null) {
111                 Utf8 sourcefile = m.getDeclaringClass().getSourceFile();
112                 int bc_index = cc.getBytecodeIndex(ip);
113                 int line_num = m.getLineNumber(bc_index);
114                 s = "\tat " + m + " (" + sourcefile + ":" + line_num + " bc:" + bc_index + " off:" + Strings.hex(code_offset) + ")";
115             } else {
116                 s = "\tat <unknown cc> (start:" + cc.getStart().stringRep() + " off:" + Strings.hex(code_offset) + ")";
117             }
118         } else {
119             s = "\tat <unknown addr> (ip:" + ip.stringRep() + ")";
120         }
121         return s;
122     }
123     
124     public static void stackDump(CodeAddress init_ip, StackAddress init_fp) {
125         StackCodeWalker sw = new StackCodeWalker(init_ip, init_fp);
126         while (sw.hasNext()) {
127             String s = sw.toString();
128             SystemInterface.debugwriteln(s);
129             sw.gotoNext();
130         }
131     }
132 
133 }