/******************************************************************************* * Copyright (c) 2002,2006 IBM Corporation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package com.ibm.wala.shrikeBT.shrikeCT.tools; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.PrintWriter; import com.ibm.wala.shrikeBT.Decoder; import com.ibm.wala.shrikeBT.Disassembler; import com.ibm.wala.shrikeBT.MethodData; import com.ibm.wala.shrikeBT.analysis.Analyzer.FailureException; import com.ibm.wala.shrikeBT.analysis.ClassHierarchyStore; import com.ibm.wala.shrikeBT.analysis.Verifier; import com.ibm.wala.shrikeBT.shrikeCT.CTDecoder; import com.ibm.wala.shrikeBT.shrikeCT.CTUtils; import com.ibm.wala.shrikeBT.shrikeCT.ClassInstrumenter; import com.ibm.wala.shrikeBT.shrikeCT.OfflineInstrumenter; import com.ibm.wala.shrikeCT.ClassReader; import com.ibm.wala.shrikeCT.CodeReader; import com.ibm.wala.shrikeCT.InvalidClassFileException; /** * This is a demo class. * * Class files are taken as input arguments (or if there are none, from standard input). The methods in those files are * instrumented: we insert a System.err.println() at ever method call, and a System.err.println() at every method entry. * * In Unix, I run it like this: java -cp ~/dev/shrike/shrike com.ibm.wala.shrikeBT.shrikeCT.tools.BatchVerifier test.jar -o * output.jar * * The instrumented classes are placed in the directory "output" under the current directory. Disassembled code is written to the * file "report" under the current directory. */ public class BatchVerifier { private static boolean disasm = false; final private static ClassHierarchyStore store = new ClassHierarchyStore(); private static int errors = 0; public static void main(String[] args) throws Exception { OfflineInstrumenter oi = new OfflineInstrumenter(true); args = oi.parseStandardArgs(args); for (int i = 0; i < args.length; i++) { if (args[i].equals("-d")) { disasm = true; } } PrintWriter w = new PrintWriter(new BufferedWriter(new FileWriter("report", false))); oi.beginTraversal(); ClassInstrumenter ci; while ((ci = oi.nextClass()) != null) { ClassReader cr = ci.getReader(); CTUtils.addClassToHierarchy(store, cr); } oi.beginTraversal(); while ((ci = oi.nextClass()) != null) { doClass(ci.getReader(), w); } oi.close(); if (errors > 0) { System.err.println(errors + " error" + (errors > 1 ? "s" : "") + " detected"); } } private static void doClass(final ClassReader cr, PrintWriter w) throws Exception { int methodCount = cr.getMethodCount(); w.write("Verifying " + cr.getName() + "\n"); w.flush(); ClassReader.AttrIterator iter = new ClassReader.AttrIterator(); for (int i = 0; i < methodCount; i++) { cr.initMethodAttributeIterator(i, iter); for (; iter.isValid(); iter.advance()) { if (iter.getName().equals("Code")) { w.write("Verifying " + cr.getName() + "." + cr.getMethodName(i) + " " + cr.getMethodType(i) + ":\n"); w.flush(); CodeReader code = new CodeReader(iter); CTDecoder d = new CTDecoder(code); try { d.decode(); } catch (Decoder.InvalidBytecodeException e) { throw new InvalidClassFileException(code.getRawOffset(), e.getMessage()); } MethodData md = new MethodData(d, cr.getMethodAccessFlags(i), CTDecoder.convertClassToType(cr.getName()), cr .getMethodName(i), cr.getMethodType(i)); if (disasm) { w.write("ShrikeBT code:\n"); (new Disassembler(md)).disassembleTo(w); w.flush(); } Verifier v = new Verifier(md); try { v.verify(); } catch (FailureException e) { w.println("ERROR: VERIFICATION FAILED"); e.printStackTrace(w); e.printPath(w); errors++; w.flush(); } break; } } } } }