1
2
3
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
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 }