2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
6 * The Java Pathfinder core (jpf-core) platform is licensed under the
7 * Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0.
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package gov.nasa.jpf.listener;
20 import gov.nasa.jpf.Config;
21 import gov.nasa.jpf.JPF;
22 import gov.nasa.jpf.ListenerAdapter;
23 import gov.nasa.jpf.jvm.bytecode.INVOKESPECIAL;
24 import gov.nasa.jpf.jvm.bytecode.JVMInvokeInstruction;
25 import gov.nasa.jpf.jvm.bytecode.VirtualInvocation;
26 import gov.nasa.jpf.search.Search;
27 import gov.nasa.jpf.vm.Instruction;
28 import gov.nasa.jpf.vm.MJIEnv;
29 import gov.nasa.jpf.vm.VM;
30 import gov.nasa.jpf.vm.MethodInfo;
31 import gov.nasa.jpf.vm.ThreadInfo;
33 import java.io.PrintWriter;
36 * simple tool to log method invocations
38 * at this point, it doesn't do fancy things yet, but gives a more high
39 * level idea of what got executed by JPF than the ExecTracker
41 public class MethodTracker extends ListenerAdapter {
43 static final String INDENT = " ";
48 public MethodTracker (Config conf, JPF jpf) {
49 out = new PrintWriter(System.out, true);
52 void logMethodCall(ThreadInfo ti, MethodInfo mi, int stackDepth) {
53 out.print(ti.getId());
56 for (int i=0; i<stackDepth%80; i++) {
64 out.print(mi.getFullName());
66 if (ti.isFirstStepInsn()) {
74 public void executeInstruction (VM vm, ThreadInfo ti, Instruction insnToExecute) {
75 MethodInfo mi = insnToExecute.getMethodInfo();
78 logMethodCall(ti, mi, ti.getStackDepth());
81 } else if (insnToExecute instanceof JVMInvokeInstruction) {
84 // that's the only little gist of it - if this is a VirtualInvocation,
85 // we have to dig the callee out by ourselves (it's not known
88 if (insnToExecute instanceof VirtualInvocation) {
89 VirtualInvocation callInsn = (VirtualInvocation)insnToExecute;
90 int objref = callInsn.getCalleeThis(ti);
91 if (objref != MJIEnv.NULL){
92 callee = callInsn.getInvokedMethod(ti, objref);
94 return; // this is causing a NPE, so don't report it as a unknown callee
97 } else if (insnToExecute instanceof INVOKESPECIAL) {
98 INVOKESPECIAL callInsn = (INVOKESPECIAL)insnToExecute;
99 callee = callInsn.getInvokedMethod(ti);
102 JVMInvokeInstruction callInsn = (JVMInvokeInstruction)insnToExecute;
103 callee = callInsn.getInvokedMethod(ti);
106 if (callee != null) {
107 if (callee.isMJI()) {
108 logMethodCall(ti, callee, ti.getStackDepth()+1);
111 out.println("ERROR: unknown callee of: " + insnToExecute);
117 * those are not really required, but mark the transition boundaries
120 public void stateRestored(Search search) {
121 int id = search.getStateId();
122 out.println("----------------------------------- [" +
123 search.getDepth() + "] restored: " + id);
126 //--- the ones we are interested in
128 public void searchStarted(Search search) {
129 out.println("----------------------------------- search started");
133 public void stateAdvanced(Search search) {
134 int id = search.getStateId();
136 out.print("----------------------------------- [" +
137 search.getDepth() + "] forward: " + id);
138 if (search.isNewState()) {
141 out.print(" visited");
144 if (search.isEndState()) {
154 public void stateBacktracked(Search search) {
155 int id = search.getStateId();
159 out.println("----------------------------------- [" +
160 search.getDepth() + "] backtrack: " + id);
164 public void searchFinished(Search search) {
165 out.println("----------------------------------- search finished");