KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jode > obfuscator > modules > SimpleAnalyzer


1 /* SimpleAnalyzer Copyright (C) 1999-2002 Jochen Hoenicke.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; see the file COPYING. If not, write to
15  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
16  *
17  * $Id: SimpleAnalyzer.java.in,v 1.1.2.2 2002/05/28 17:34:17 hoenicke Exp $
18  */

19
20 package jode.obfuscator.modules;
21 import jode.bytecode.Handler;
22 import jode.bytecode.Opcodes;
23 import jode.bytecode.ClassInfo;
24 import jode.bytecode.BytecodeInfo;
25 import jode.bytecode.Instruction;
26 import jode.bytecode.Reference;
27 import jode.bytecode.TypeSignature;
28 import jode.obfuscator.Identifier;
29 import jode.obfuscator.*;
30 import jode.GlobalOptions;
31
32 import java.util.Iterator JavaDoc;
33 import java.util.ListIterator JavaDoc;
34
35 public class SimpleAnalyzer implements CodeAnalyzer, Opcodes {
36
37     private ClassInfo canonizeIfaceRef(ClassInfo clazz, Reference ref) {
38     while (clazz != null) {
39         if (clazz.findMethod(ref.getName(), ref.getType()) != null)
40         return clazz;
41         ClassInfo[] ifaces = clazz.getInterfaces();
42         for (int i = 0; i < ifaces.length; i++) {
43         ClassInfo realClass = canonizeIfaceRef(ifaces[i], ref);
44         if (realClass != null)
45             return realClass;
46         }
47         clazz = clazz.getSuperclass();
48     }
49     return null;
50     }
51
52     public Identifier canonizeReference(Instruction instr) {
53     Reference ref = instr.getReference();
54     Identifier ident = Main.getClassBundle().getIdentifier(ref);
55     String JavaDoc clName = ref.getClazz();
56     String JavaDoc realClazzName;
57     if (ident != null) {
58         ClassIdentifier clazz = (ClassIdentifier)ident.getParent();
59         realClazzName = "L" + (clazz.getFullName()
60                    .replace('.', '/')) + ";";
61     } else {
62         /* We have to look at the ClassInfo's instead, to
63          * point to the right method.
64          */

65         ClassInfo clazz;
66         if (clName.charAt(0) == '[') {
67         /* Arrays don't define new methods (well clone(),
68          * but that can be ignored).
69          */

70         clazz = ClassInfo.javaLangObject;
71         } else {
72         clazz = ClassInfo.forName
73             (clName.substring(1, clName.length()-1)
74              .replace('/','.'));
75         }
76         if (instr.getOpcode() == opc_invokeinterface) {
77         clazz = canonizeIfaceRef(clazz, ref);
78         } else if (instr.getOpcode() >= opc_invokevirtual) {
79         while (clazz != null
80                && clazz.findMethod(ref.getName(),
81                        ref.getType()) == null)
82             clazz = clazz.getSuperclass();
83         } else {
84         while (clazz != null
85                && clazz.findField(ref.getName(),
86                       ref.getType()) == null)
87             clazz = clazz.getSuperclass();
88         }
89
90         if (clazz == null) {
91         GlobalOptions.err.println("WARNING: Can't find reference: "
92                       +ref);
93         realClazzName = clName;
94         } else
95         realClazzName = "L" + clazz.getName().replace('.', '/') + ";";
96     }
97     if (!realClazzName.equals(ref.getClazz())) {
98         ref = Reference.getReference(realClazzName,
99                      ref.getName(), ref.getType());
100         instr.setReference(ref);
101     }
102     return ident;
103     }
104
105
106     /**
107      * Reads the opcodes out of the code info and determine its
108      * references
109      * @return an enumeration of the references.
110      */

111     public void analyzeCode(MethodIdentifier m, BytecodeInfo bytecode) {
112     for (Iterator JavaDoc iter = bytecode.getInstructions().iterator();
113          iter.hasNext(); ) {
114         Instruction instr = (Instruction) iter.next();
115         switch (instr.getOpcode()) {
116         case opc_checkcast:
117         case opc_instanceof:
118         case opc_multianewarray: {
119         String JavaDoc clName = instr.getClazzType();
120         int i = 0;
121         while (i < clName.length() && clName.charAt(i) == '[')
122             i++;
123         if (i < clName.length() && clName.charAt(i) == 'L') {
124             clName = clName.substring(i+1, clName.length()-1)
125             .replace('/','.');
126             Main.getClassBundle().reachableClass(clName);
127         }
128         break;
129         }
130         case opc_invokespecial:
131         case opc_invokestatic:
132         case opc_invokeinterface:
133         case opc_invokevirtual:
134         case opc_putstatic:
135         case opc_putfield:
136         m.setGlobalSideEffects();
137         /* fall through */
138         case opc_getstatic:
139         case opc_getfield: {
140         Identifier ident = canonizeReference(instr);
141         if (ident != null) {
142             if (instr.getOpcode() == opc_putstatic
143             || instr.getOpcode() == opc_putfield) {
144             FieldIdentifier fi = (FieldIdentifier) ident;
145             if (fi != null && !fi.isNotConstant())
146                 fi.setNotConstant();
147             } else if (instr.getOpcode() == opc_invokevirtual
148                    || instr.getOpcode() == opc_invokeinterface) {
149             ((ClassIdentifier) ident.getParent())
150                 .reachableReference(instr.getReference(), true);
151             } else {
152             ident.setReachable();
153             }
154         }
155         break;
156         }
157         }
158     }
159
160     Handler[] handlers = bytecode.getExceptionHandlers();
161     for (int i=0; i< handlers.length; i++) {
162         if (handlers[i].type != null)
163         Main.getClassBundle()
164             .reachableClass(handlers[i].type);
165     }
166     }
167
168     public void transformCode(BytecodeInfo bytecode) {
169     for (ListIterator JavaDoc iter = bytecode.getInstructions().listIterator();
170          iter.hasNext(); ) {
171         Instruction instr = (Instruction) iter.next();
172         if (instr.getOpcode() == opc_putstatic
173         || instr.getOpcode() == opc_putfield) {
174         Reference ref = instr.getReference();
175         FieldIdentifier fi = (FieldIdentifier)
176             Main.getClassBundle().getIdentifier(ref);
177         if (fi != null
178             && (Main.stripping & Main.STRIP_UNREACH) != 0
179             && !fi.isReachable()) {
180             /* Replace instruction with pop opcodes. */
181             int stacksize =
182             (instr.getOpcode()
183              == Instruction.opc_putstatic) ? 0 : 1;
184             stacksize += TypeSignature.getTypeSize(ref.getType());
185             switch (stacksize) {
186             case 1:
187             iter.set(new Instruction(Instruction.opc_pop));
188             break;
189             case 2:
190             iter.set(new Instruction(Instruction.opc_pop2));
191             break;
192             case 3:
193             iter.set(new Instruction(Instruction.opc_pop2));
194             iter.add(new Instruction(Instruction.opc_pop));
195             break;
196             }
197         }
198         }
199     }
200     }
201 }
202
Popular Tags