cl.inria.stiq.db.structure.analysis.Disassembler.java Source code

Java tutorial

Introduction

Here is the source code for cl.inria.stiq.db.structure.analysis.Disassembler.java

Source

/*
TOD - Trace Oriented Debugger.
Copyright (c) 2006-2008, Guillaume Pothier
All rights reserved.
    
This program is free software; you can redistribute it and/or 
modify it under the terms of the GNU General Public License 
version 2 as published by the Free Software Foundation.
    
This program is distributed in the hope that it will be useful, 
but WITHOUT ANY WARRANTY; without even the implied warranty of 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
General Public License for more details.
    
You should have received a copy of the GNU General Public License 
along with this program; if not, write to the Free Software 
Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
MA 02111-1307 USA
    
Parts of this work rely on the MD5 algorithm "derived from the 
RSA Data Security, Inc. MD5 Message-Digest Algorithm".
*/
package cl.inria.stiq.db.structure.analysis;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.util.TraceMethodVisitor;

import zz.utils.Utils;
import cl.inria.stiq.config.TODConfig;
import cl.inria.stiq.db.structure.IBehaviorInfo;
import cl.inria.stiq.db.structure.IClassInfo;
import cl.inria.stiq.db.structure.IMutableBehaviorInfo;
import cl.inria.stiq.db.structure.analysis.DisassembledBehavior.Instruction;
import cl.inria.stiq.db.structure.impl.ClassInfo;
import cl.inria.stiq.db.structure.impl.StructureDatabase;

public class Disassembler {
    public static void main(String[] args) throws IOException {
        File f = new File(TODConfig.TMPDIR + "/Fixtures.class");
        byte[] theBytecode = Utils.readInputStream_byte(new FileInputStream(f));

        StructureDatabase theStructureDatabase = StructureDatabase.create(new TODConfig(), true);
        ClassInfo theClass = theStructureDatabase.getNewClass("dummy.Dummy");
        theClass.setBytecode(theBytecode, theBytecode);

        IMutableBehaviorInfo theBehavior = theClass.getNewBehavior("checkCondition",
                "(Ltod/impl/database/IBidiIterator;Ltod/impl/evdbng/queries/EventCondition;Ltod/impl/evdbng/EventGenerator;I)I",
                0);

        DisassembledBehavior theDisassembledBehavior = disassemble(theBehavior);
        System.out.println(theDisassembledBehavior);
    }

    public static DisassembledBehavior disassemble(IBehaviorInfo aBehavior) {
        IClassInfo theClass = aBehavior.getDeclaringType();
        MethodNode theMethodNode = null;
        ClassReader cr = null;

        byte[] theBytecode = theClass.getBytecode().instrumented;
        if (theBytecode != null) {
            cr = new ClassReader(theBytecode);
            ClassNode cn = new ClassNode();
            cr.accept(cn, 0);

            // Search the requested method
            String theSig = aBehavior.getDescriptor();
            for (Iterator theIterator = cn.methods.iterator(); theIterator.hasNext();) {
                MethodNode theMethod = (MethodNode) theIterator.next();
                if (!theMethod.name.equals(aBehavior.getName()))
                    continue;
                if (!theMethod.desc.equals(theSig))
                    continue;
                theMethodNode = theMethod;
                break;
            }
        }

        if (theMethodNode == null)
            return null;

        MyTraceMethodVisitor theVisitor = new MyTraceMethodVisitor(cr);
        theMethodNode.accept(theVisitor);

        return new DisassembledBehavior(aBehavior, theVisitor.getInstructions());

    }

    /**
     * We subclass ASM's {@link TraceMethodVisitor} so as to capture disassembled
     * bytecodes.
     * @author gpothier
     */
    private static class MyTraceMethodVisitor extends TraceMethodVisitor {
        private List<Instruction> itsInstructions = new ArrayList<Instruction>();

        public Instruction[] getInstructions() {
            return itsInstructions.toArray(new Instruction[itsInstructions.size()]);
        }

        public MyTraceMethodVisitor(ClassReader aReader) {
            super(new ClassWriter(aReader, 0).visitMethod(0, "", "", "", null));
        }

        /**
         * Returns the current bytecode offset.
         */
        private int getPc() {
            Label l = new Label();
            mv.visitLabel(l);
            return l.getOffset();
        }

        private void addInstruction(int aPc) {
            itsInstructions.add(new Instruction(aPc, buf.toString().trim(), false));
        }

        private void addLabel(int aPc) {
            itsInstructions.add(new Instruction(aPc, buf.toString().trim(), true));
        }

        @Override
        public void visitFieldInsn(int aOpcode, String aOwner, String aName, String aDesc) {
            int thePc = getPc();
            super.visitFieldInsn(aOpcode, aOwner, aName, aDesc);
            addInstruction(thePc);
        }

        @Override
        public void visitIincInsn(int aVar, int aIncrement) {
            int thePc = getPc();
            super.visitIincInsn(aVar, aIncrement);
            addInstruction(thePc);
        }

        @Override
        public void visitInsn(int aOpcode) {
            int thePc = getPc();
            super.visitInsn(aOpcode);
            addInstruction(thePc);
        }

        @Override
        public void visitIntInsn(int aOpcode, int aOperand) {
            int thePc = getPc();
            super.visitIntInsn(aOpcode, aOperand);
            addInstruction(thePc);
        }

        @Override
        public void visitJumpInsn(int aOpcode, Label aLabel) {
            int thePc = getPc();
            super.visitJumpInsn(aOpcode, aLabel);
            addInstruction(thePc);
        }

        @Override
        public void visitLdcInsn(Object aCst) {
            int thePc = getPc();
            super.visitLdcInsn(aCst);
            addInstruction(thePc);
        }

        @Override
        public void visitLookupSwitchInsn(Label aDflt, int[] aKeys, Label[] aLabels) {
            int thePc = getPc();
            super.visitLookupSwitchInsn(aDflt, aKeys, aLabels);
            addInstruction(thePc);
        }

        @Override
        public void visitMethodInsn(int aOpcode, String aOwner, String aName, String aDesc) {
            int thePc = getPc();
            super.visitMethodInsn(aOpcode, aOwner, aName, aDesc);
            addInstruction(thePc);
        }

        @Override
        public void visitMultiANewArrayInsn(String aDesc, int aDims) {
            int thePc = getPc();
            super.visitMultiANewArrayInsn(aDesc, aDims);
            addInstruction(thePc);
        }

        @Override
        public void visitTableSwitchInsn(int aMin, int aMax, Label aDflt, Label[] aLabels) {
            int thePc = getPc();
            super.visitTableSwitchInsn(aMin, aMax, aDflt, aLabels);
            addInstruction(thePc);
        }

        @Override
        public void visitTypeInsn(int aOpcode, String aDesc) {
            int thePc = getPc();
            super.visitTypeInsn(aOpcode, aDesc);
            addInstruction(thePc);
        }

        @Override
        public void visitVarInsn(int aOpcode, int aVar) {
            int thePc = getPc();
            super.visitVarInsn(aOpcode, aVar);
            addInstruction(thePc);
        }

        @Override
        public void visitLabel(Label aLabel) {
            int thePc = getPc();
            super.visitLabel(aLabel);
            addLabel(thePc);
        }

    }
}