├── .gitignore ├── LICENSE.txt ├── README.textile ├── README.txt ├── build.xml ├── documentation └── api │ ├── allclasses-frame.html │ ├── allclasses-noframe.html │ ├── bytecodeparser │ ├── CodeParser.html │ ├── Context.html │ ├── MultiMarkerCodeIterator.html │ ├── OpHandler.html │ ├── analysis │ │ ├── LocalVariable.html │ │ ├── LocalVariableType.html │ │ ├── Opcodes.OpParameterType.html │ │ ├── Opcodes.html │ │ ├── decoders │ │ │ ├── DecodedArrayCreationOp.html │ │ │ ├── DecodedArrayOp.html │ │ │ ├── DecodedBasicOp.html │ │ │ ├── DecodedBranchOp.html │ │ │ ├── DecodedConstantPushOp.html │ │ │ ├── DecodedFieldOp.html │ │ │ ├── DecodedLocalVariableOp.html │ │ │ ├── DecodedMethodInvocationOp.MethodParam.html │ │ │ ├── DecodedMethodInvocationOp.MethodParams.html │ │ │ ├── DecodedMethodInvocationOp.html │ │ │ ├── DecodedOp.html │ │ │ ├── DecodedSwitchOpcode.html │ │ │ ├── DecodedWideOp.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ └── package-tree.html │ │ ├── opcodes │ │ │ ├── ArrayCreationOpcode.html │ │ │ ├── ArrayOpcode.html │ │ │ ├── BasicOpcode.html │ │ │ ├── BranchOpCode.html │ │ │ ├── ConstantPushOpcode.html │ │ │ ├── ExitOpcode.html │ │ │ ├── FieldOpcode.html │ │ │ ├── LocalVariableOpcode.html │ │ │ ├── MethodInvocationOpcode.html │ │ │ ├── Op.html │ │ │ ├── SwitchOpcode.html │ │ │ ├── WideOpcode.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ └── package-tree.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ ├── package-tree.html │ │ └── stack │ │ │ ├── Array.html │ │ │ ├── Constant.DoubleConstant.html │ │ │ ├── Constant.FloatConstant.html │ │ │ ├── Constant.IntegerConstant.html │ │ │ ├── Constant.LongConstant.html │ │ │ ├── Constant.StringConstant.html │ │ │ ├── Constant.WhateverConstant.html │ │ │ ├── Constant.html │ │ │ ├── Stack.StackElementLength.html │ │ │ ├── Stack.html │ │ │ ├── StackAnalyzer.Frame.html │ │ │ ├── StackAnalyzer.Frames.FrameIterator.html │ │ │ ├── StackAnalyzer.Frames.html │ │ │ ├── StackAnalyzer.html │ │ │ ├── StackElement.html │ │ │ ├── TOP.html │ │ │ ├── TrackableArray.html │ │ │ ├── ValueFromLocalVariable.html │ │ │ ├── VoidElement.html │ │ │ ├── Whatever.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ └── package-tree.html │ ├── package-frame.html │ ├── package-summary.html │ ├── package-tree.html │ └── utils │ │ ├── Utils.html │ │ ├── package-frame.html │ │ ├── package-summary.html │ │ └── package-tree.html │ ├── constant-values.html │ ├── deprecated-list.html │ ├── help-doc.html │ ├── index-all.html │ ├── index.html │ ├── overview-frame.html │ ├── overview-summary.html │ ├── overview-tree.html │ ├── package-list │ ├── resources │ └── inherit.gif │ └── stylesheet.css ├── gpl-3.0.txt ├── lgpl-3.0.txt ├── lib ├── javassist.jar ├── junit-4.8.2.jar └── log4j-1.2.16.jar ├── log4j.properties.test.jar ├── pom.xml └── src ├── bytecodeparser ├── CodeParser.java ├── Context.java ├── MultiMarkerCodeIterator.java ├── OpHandler.java ├── analysis │ ├── LocalVariable.java │ ├── LocalVariableType.java │ ├── Opcodes.java │ ├── decoders │ │ ├── DecodedArrayCreationOp.java │ │ ├── DecodedArrayOp.java │ │ ├── DecodedBasicOp.java │ │ ├── DecodedBranchOp.java │ │ ├── DecodedConstantPushOp.java │ │ ├── DecodedFieldOp.java │ │ ├── DecodedLocalVariableOp.java │ │ ├── DecodedMethodInvocationOp.java │ │ ├── DecodedOp.java │ │ ├── DecodedSwitchOpcode.java │ │ └── DecodedWideOp.java │ ├── opcodes │ │ ├── ArrayCreationOpcode.java │ │ ├── ArrayOpcode.java │ │ ├── BasicOpcode.java │ │ ├── BranchOpCode.java │ │ ├── ConstantPushOpcode.java │ │ ├── ExitOpcode.java │ │ ├── FieldOpcode.java │ │ ├── LocalVariableOpcode.java │ │ ├── MethodInvocationOpcode.java │ │ ├── Op.java │ │ ├── SwitchOpcode.java │ │ └── WideOpcode.java │ └── stack │ │ ├── Array.java │ │ ├── Constant.java │ │ ├── Stack.java │ │ ├── StackAnalyzer.java │ │ ├── StackElement.java │ │ ├── TOP.java │ │ ├── TrackableArray.java │ │ ├── ValueFromLocalVariable.java │ │ ├── VoidElement.java │ │ └── Whatever.java └── utils │ └── Utils.java └── test ├── CommonTests.java ├── Test.java ├── coucou.yml └── subjects ├── Common.java ├── SimpleSubjects.java ├── Subject.java └── WideTestSubject.java /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | BytecodeParser, Copyright (C) 2011 Stephane Godbillon 2 | 3 | BytecodeParser is released under the GNU Lesser General Public License 4 | (LGPL), version 3 (or any later version at your option). 5 | 6 | You should have received a copy of the GNU Lesser General Public License 7 | along with BytecodeParser. If not, see . 8 | -------------------------------------------------------------------------------- /README.textile: -------------------------------------------------------------------------------- 1 | h1. BytecodeParser 2 | 3 | p. BytecodeParser is a java library that can help you statically to parse java bytecode by extracting as much information as possible. It is based upon "javassist":http://www.csg.is.titech.ac.jp/~chiba/javassist/. 4 | 5 | p. It can also statically analyze each method's frame, for particular purposes like retrieving the names of the local variable names given as parameters of a method call (its original purpose), check if all the frames are reachable, etc. 6 | 7 | p. BytecodeParser simulates the stack operations made by the opcodes in the CodeAttribute. It can give you the state of the stack before and after the frame is run. 8 | 9 | p. BytecodeParser is released under the "LGPL, version 3":http://www.gnu.org/licenses/lgpl.html. It is actively developped. You can download the latest version ("v0.3":http://sgodbillon.github.com/BytecodeParser/releases/0.3/bytecodeparser-0.3.jar), explore its capabilities and extend it if you need to. 10 | 11 | h2. How to use it 12 | 13 | p. See the "project's website":http://sgodbillon.github.com/BytecodeParser/ for detailed examples and more information. You can also "browse the API":http://sgodbillon.github.com/BytecodeParser/releases/0.3/api/index.html. 14 | 15 | h2. A small example 16 | 17 | bc. ClassPool cp = new ClassPool(); 18 | CtClass ctClass = cp.getCtClass("org.myapp.MyClass"); 19 | for(CtMethod method: ctClass.getMethods()) { 20 | StackAnalyzer stackAnalyzer = new StackAnalyzer(method); 21 | for(Frame frame: stackAnalyzer.analyze()) { 22 | // you can get the state of the stack before or after this frame with frame.stackBefore and frame.stackAfter 23 | System.out.println(frame.stackBefore + " => " + frame.stackAfter); 24 | // you can also get some extended information about this frame with frame.decodedOp 25 | if(frame.decodedOp instanceof DecodedMethodInvocationOp) { 26 | DecodedMethodInvocationOp dmio = (DecodedMethodInvocationOp) frame.decodedOp; 27 | MethodParams methodParams = DecodedMethodInvocationOp.resolveParameters(frame); 28 | MethodParam[] params = methodParams.merge(); 29 | System.out.println("method '" + dmio.getName() + "' has been called with the following arguments: " + java.util.Arrays.toString(params)); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2011 Stephane Godbillon 2 | 3 | BytecodeParser is a java library that can help you statically to parse java 4 | bytecode by extracting as much information as possible. It can also statically 5 | analyze each method's frame, for particular purposes like retrieving the names 6 | of the local variable names given as parameters of a method call (its original 7 | purpose), check if all the frames are reachable, etc. 8 | 9 | BytecodeParser is released under the GNU Lesser General Public License 10 | (LGPL), version 3 (or any later version at your option). 11 | 12 | BytecodeParser is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU Lesser General Public License as published by 14 | the Free Software Foundation, either version 3 of the License, or 15 | (at your option) any later version. 16 | 17 | BytecodeParser is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU Lesser General Public License for more details. 21 | 22 | You should have received a copy of the GNU Lesser General Public License 23 | along with BytecodeParser. If not, see . -------------------------------------------------------------------------------- /build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /documentation/api/allclasses-noframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | All Classes (BytecodeParser API) 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | All Classes 20 |
21 | 22 | 23 | 24 | 131 | 132 |
Array 25 |
26 | ArrayCreationOpcode 27 |
28 | ArrayOpcode 29 |
30 | BasicOpcode 31 |
32 | BranchOpCode 33 |
34 | CodeParser 35 |
36 | Constant 37 |
38 | Constant.DoubleConstant 39 |
40 | Constant.FloatConstant 41 |
42 | Constant.IntegerConstant 43 |
44 | Constant.LongConstant 45 |
46 | Constant.StringConstant 47 |
48 | Constant.WhateverConstant 49 |
50 | ConstantPushOpcode 51 |
52 | Context 53 |
54 | DecodedArrayCreationOp 55 |
56 | DecodedArrayOp 57 |
58 | DecodedBasicOp 59 |
60 | DecodedBranchOp 61 |
62 | DecodedConstantPushOp 63 |
64 | DecodedFieldOp 65 |
66 | DecodedLocalVariableOp 67 |
68 | DecodedMethodInvocationOp 69 |
70 | DecodedMethodInvocationOp.MethodParam 71 |
72 | DecodedMethodInvocationOp.MethodParams 73 |
74 | DecodedOp 75 |
76 | DecodedSwitchOpcode 77 |
78 | DecodedWideOp 79 |
80 | ExitOpcode 81 |
82 | FieldOpcode 83 |
84 | LocalVariable 85 |
86 | LocalVariableOpcode 87 |
88 | LocalVariableType 89 |
90 | MethodInvocationOpcode 91 |
92 | MultiMarkerCodeIterator 93 |
94 | Op 95 |
96 | Opcodes 97 |
98 | Opcodes.OpParameterType 99 |
100 | OpHandler 101 |
102 | Stack 103 |
104 | Stack.StackElementLength 105 |
106 | StackAnalyzer 107 |
108 | StackAnalyzer.Frame 109 |
110 | StackAnalyzer.Frames 111 |
112 | StackElement 113 |
114 | SwitchOpcode 115 |
116 | TOP 117 |
118 | TrackableArray 119 |
120 | Utils 121 |
122 | ValueFromLocalVariable 123 |
124 | VoidElement 125 |
126 | Whatever 127 |
128 | WideOpcode 129 |
130 |
133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /documentation/api/bytecodeparser/analysis/decoders/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | bytecodeparser.analysis.decoders (BytecodeParser API) 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | bytecodeparser.analysis.decoders 20 | 21 | 22 | 51 | 52 |
23 | Classes  24 | 25 |
26 | DecodedArrayCreationOp 27 |
28 | DecodedArrayOp 29 |
30 | DecodedBasicOp 31 |
32 | DecodedBranchOp 33 |
34 | DecodedConstantPushOp 35 |
36 | DecodedFieldOp 37 |
38 | DecodedLocalVariableOp 39 |
40 | DecodedMethodInvocationOp 41 |
42 | DecodedMethodInvocationOp.MethodParam 43 |
44 | DecodedMethodInvocationOp.MethodParams 45 |
46 | DecodedOp 47 |
48 | DecodedSwitchOpcode 49 |
50 | DecodedWideOp
53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /documentation/api/bytecodeparser/analysis/opcodes/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | bytecodeparser.analysis.opcodes (BytecodeParser API) 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | bytecodeparser.analysis.opcodes 20 | 21 | 22 | 49 | 50 |
23 | Classes  24 | 25 |
26 | ArrayCreationOpcode 27 |
28 | ArrayOpcode 29 |
30 | BasicOpcode 31 |
32 | BranchOpCode 33 |
34 | ConstantPushOpcode 35 |
36 | ExitOpcode 37 |
38 | FieldOpcode 39 |
40 | LocalVariableOpcode 41 |
42 | MethodInvocationOpcode 43 |
44 | Op 45 |
46 | SwitchOpcode 47 |
48 | WideOpcode
51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /documentation/api/bytecodeparser/analysis/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | bytecodeparser.analysis (BytecodeParser API) 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | bytecodeparser.analysis 20 | 21 | 22 | 31 | 32 |
23 | Classes  24 | 25 |
26 | LocalVariable 27 |
28 | LocalVariableType 29 |
30 | Opcodes
33 | 34 | 35 | 36 | 37 | 42 | 43 |
38 | Enums  39 | 40 |
41 | Opcodes.OpParameterType
44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /documentation/api/bytecodeparser/analysis/package-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | bytecodeparser.analysis (BytecodeParser API) 8 | 9 | 10 | 11 | 12 | 13 | 14 | 22 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 50 | 53 | 54 | 55 | 56 | 59 | 75 | 76 |
51 | 52 |
77 | 78 | 79 | 80 |
81 |

82 | Package bytecodeparser.analysis 83 |

84 | 85 | 86 | 87 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 |
88 | Class Summary
LocalVariableA local variable.
LocalVariableTypeInformation about a localVariable type.
OpcodesThe opcodes that are used by the JVM, and their handling classes.
103 |   104 | 105 |

106 | 107 | 108 | 109 | 111 | 112 | 113 | 114 | 115 | 116 |
110 | Enum Summary
Opcodes.OpParameterTypeA Parameter of an opcode.
117 |   118 | 119 |

120 |

121 |
122 |
123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 144 | 147 | 148 | 149 | 150 | 153 | 169 | 170 |
145 | 146 |
171 | 172 | 173 | 174 |
175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /documentation/api/bytecodeparser/analysis/package-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | bytecodeparser.analysis Class Hierarchy (BytecodeParser API) 8 | 9 | 10 | 11 | 12 | 13 | 14 | 22 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 50 | 53 | 54 | 55 | 56 | 59 | 75 | 76 |
51 | 52 |
77 | 78 | 79 | 80 |
81 |
82 |

83 | Hierarchy For Package bytecodeparser.analysis 84 |

85 |
86 |
87 |
Package Hierarchies:
All Packages
88 |
89 |

90 | Class Hierarchy 91 |

92 | 96 |

97 | Enum Hierarchy 98 |

99 | 106 |
107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 128 | 131 | 132 | 133 | 134 | 137 | 153 | 154 |
129 | 130 |
155 | 156 | 157 | 158 |
159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /documentation/api/bytecodeparser/analysis/stack/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | bytecodeparser.analysis.stack (BytecodeParser API) 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | bytecodeparser.analysis.stack 20 | 21 | 22 | 61 | 62 |
23 | Classes  24 | 25 |
26 | Array 27 |
28 | Constant 29 |
30 | Constant.DoubleConstant 31 |
32 | Constant.FloatConstant 33 |
34 | Constant.IntegerConstant 35 |
36 | Constant.LongConstant 37 |
38 | Constant.StringConstant 39 |
40 | Constant.WhateverConstant 41 |
42 | Stack 43 |
44 | StackAnalyzer 45 |
46 | StackAnalyzer.Frame 47 |
48 | StackAnalyzer.Frames 49 |
50 | StackElement 51 |
52 | TOP 53 |
54 | TrackableArray 55 |
56 | ValueFromLocalVariable 57 |
58 | VoidElement 59 |
60 | Whatever
63 | 64 | 65 | 66 | 67 | 72 | 73 |
68 | Enums  69 | 70 |
71 | Stack.StackElementLength
74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /documentation/api/bytecodeparser/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | bytecodeparser (BytecodeParser API) 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | bytecodeparser 20 | 21 | 22 | 27 | 28 |
23 | Interfaces  24 | 25 |
26 | OpHandler
29 | 30 | 31 | 32 | 33 | 42 | 43 |
34 | Classes  35 | 36 |
37 | CodeParser 38 |
39 | Context 40 |
41 | MultiMarkerCodeIterator
44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /documentation/api/bytecodeparser/package-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | bytecodeparser (BytecodeParser API) 8 | 9 | 10 | 11 | 12 | 13 | 14 | 22 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 50 | 53 | 54 | 55 | 56 | 59 | 75 | 76 |
51 | 52 |
77 | 78 | 79 | 80 |
81 |

82 | Package bytecodeparser 83 |

84 | 85 | 86 | 87 | 89 | 90 | 91 | 92 | 93 | 94 |
88 | Interface Summary
OpHandlerA handler for opcodes, used when parsing bytecode with the CodeParser.
95 |   96 | 97 |

98 | 99 | 100 | 101 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 |
102 | Class Summary
CodeParserA basic bytecode parser.
ContextA context for parsing bytecode.
MultiMarkerCodeIteratorA code iterator that tracks more than one mark in the bytecode.
117 |   118 | 119 |

120 |

121 |
122 |
123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 144 | 147 | 148 | 149 | 150 | 153 | 169 | 170 |
145 | 146 |
171 | 172 | 173 | 174 |
175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /documentation/api/bytecodeparser/package-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | bytecodeparser Class Hierarchy (BytecodeParser API) 8 | 9 | 10 | 11 | 12 | 13 | 14 | 22 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 50 | 53 | 54 | 55 | 56 | 59 | 75 | 76 |
51 | 52 |
77 | 78 | 79 | 80 |
81 |
82 |

83 | Hierarchy For Package bytecodeparser 84 |

85 |
86 |
87 |
Package Hierarchies:
All Packages
88 |
89 |

90 | Class Hierarchy 91 |

92 | 99 |

100 | Interface Hierarchy 101 |

102 | 104 |
105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 126 | 129 | 130 | 131 | 132 | 135 | 151 | 152 |
127 | 128 |
153 | 154 | 155 | 156 |
157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /documentation/api/bytecodeparser/utils/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | bytecodeparser.utils (BytecodeParser API) 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | bytecodeparser.utils 20 | 21 | 22 | 27 | 28 |
23 | Classes  24 | 25 |
26 | Utils
29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /documentation/api/bytecodeparser/utils/package-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | bytecodeparser.utils (BytecodeParser API) 8 | 9 | 10 | 11 | 12 | 13 | 14 | 22 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 50 | 53 | 54 | 55 | 56 | 59 | 75 | 76 |
51 | 52 |
77 | 78 | 79 | 80 |
81 |

82 | Package bytecodeparser.utils 83 |

84 | 85 | 86 | 87 | 89 | 90 | 91 | 92 | 93 | 94 |
88 | Class Summary
Utils 
95 |   96 | 97 |

98 |

99 |
100 |
101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 122 | 125 | 126 | 127 | 128 | 131 | 147 | 148 |
123 | 124 |
149 | 150 | 151 | 152 |
153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /documentation/api/bytecodeparser/utils/package-tree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | bytecodeparser.utils Class Hierarchy (BytecodeParser API) 8 | 9 | 10 | 11 | 12 | 13 | 14 | 22 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 50 | 53 | 54 | 55 | 56 | 59 | 75 | 76 |
51 | 52 |
77 | 78 | 79 | 80 |
81 |
82 |

83 | Hierarchy For Package bytecodeparser.utils 84 |

85 |
86 |
87 |
Package Hierarchies:
All Packages
88 |
89 |

90 | Class Hierarchy 91 |

92 | 96 |
97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 118 | 121 | 122 | 123 | 124 | 127 | 143 | 144 |
119 | 120 |
145 | 146 | 147 | 148 |
149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /documentation/api/constant-values.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Constant Field Values (BytecodeParser API) 8 | 9 | 10 | 11 | 12 | 13 | 14 | 22 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 50 | 53 | 54 | 55 | 56 | 59 | 75 | 76 |
51 | 52 |
77 | 78 | 79 | 80 |
81 |
82 |

83 | Constant Field Values

84 |
85 |
86 | Contents 88 | 89 |
90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 111 | 114 | 115 | 116 | 117 | 120 | 136 | 137 |
112 | 113 |
138 | 139 | 140 | 141 |
142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /documentation/api/deprecated-list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Deprecated List (BytecodeParser API) 8 | 9 | 10 | 11 | 12 | 13 | 14 | 22 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 50 | 53 | 54 | 55 | 56 | 59 | 75 | 76 |
51 | 52 |
77 | 78 | 79 | 80 |
81 |
82 |

83 | Deprecated API

84 |
85 |
86 | Contents 88 | 89 |
90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 111 | 114 | 115 | 116 | 117 | 120 | 136 | 137 |
112 | 113 |
138 | 139 | 140 | 141 |
142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /documentation/api/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | BytecodeParser API 8 | 9 | 20 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | <H2> 31 | Frame Alert</H2> 32 | 33 | <P> 34 | This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. 35 | <BR> 36 | Link to<A HREF="overview-summary.html">Non-frame version.</A> 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /documentation/api/overview-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Overview List (BytecodeParser API) 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 23 | 24 |
22 |
25 | 26 | 27 | 28 | 46 | 47 |
All Classes 29 |

30 | 31 | Packages 32 |
33 | bytecodeparser 34 |
35 | bytecodeparser.analysis 36 |
37 | bytecodeparser.analysis.decoders 38 |
39 | bytecodeparser.analysis.opcodes 40 |
41 | bytecodeparser.analysis.stack 42 |
43 | bytecodeparser.utils 44 |
45 |

48 | 49 |

50 |   51 | 52 | 53 | -------------------------------------------------------------------------------- /documentation/api/overview-summary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Overview (BytecodeParser API) 8 | 9 | 10 | 11 | 12 | 13 | 14 | 22 | 24 | 25 | 26 | 27 | 28 |


29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 50 | 53 | 54 | 55 | 56 | 59 | 75 | 76 |
51 | 52 |
77 | 78 | 79 | 80 |
81 | 82 | 83 | 84 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 |
85 | Packages
bytecodeparser 
bytecodeparser.analysis 
bytecodeparser.analysis.decoders 
bytecodeparser.analysis.opcodes 
bytecodeparser.analysis.stack 
bytecodeparser.utils 
112 | 113 |

114 |  


115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 136 | 139 | 140 | 141 | 142 | 145 | 161 | 162 |
137 | 138 |
163 | 164 | 165 | 166 |
167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /documentation/api/package-list: -------------------------------------------------------------------------------- 1 | bytecodeparser 2 | bytecodeparser.analysis 3 | bytecodeparser.analysis.decoders 4 | bytecodeparser.analysis.opcodes 5 | bytecodeparser.analysis.stack 6 | bytecodeparser.utils 7 | -------------------------------------------------------------------------------- /documentation/api/resources/inherit.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sgodbillon/BytecodeParser/b24c5c54fe3fa457d79c065de33b05b2ac7797df/documentation/api/resources/inherit.gif -------------------------------------------------------------------------------- /documentation/api/stylesheet.css: -------------------------------------------------------------------------------- 1 | /* Javadoc style sheet */ 2 | 3 | /* Define colors, fonts and other style attributes here to override the defaults */ 4 | 5 | /* Page background color */ 6 | body { background-color: #FFFFFF; color:#000000 } 7 | 8 | /* Headings */ 9 | h1 { font-size: 145% } 10 | 11 | /* Table colors */ 12 | .TableHeadingColor { background: #CCCCFF; color:#000000 } /* Dark mauve */ 13 | .TableSubHeadingColor { background: #EEEEFF; color:#000000 } /* Light mauve */ 14 | .TableRowColor { background: #FFFFFF; color:#000000 } /* White */ 15 | 16 | /* Font used in left-hand frame lists */ 17 | .FrameTitleFont { font-size: 100%; font-family: Helvetica, Arial, sans-serif; color:#000000 } 18 | .FrameHeadingFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 } 19 | .FrameItemFont { font-size: 90%; font-family: Helvetica, Arial, sans-serif; color:#000000 } 20 | 21 | /* Navigation bar fonts and colors */ 22 | .NavBarCell1 { background-color:#EEEEFF; color:#000000} /* Light mauve */ 23 | .NavBarCell1Rev { background-color:#00008B; color:#FFFFFF} /* Dark Blue */ 24 | .NavBarFont1 { font-family: Arial, Helvetica, sans-serif; color:#000000;color:#000000;} 25 | .NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;color:#FFFFFF;} 26 | 27 | .NavBarCell2 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000} 28 | .NavBarCell3 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000} 29 | 30 | -------------------------------------------------------------------------------- /lgpl-3.0.txt: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /lib/javassist.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sgodbillon/BytecodeParser/b24c5c54fe3fa457d79c065de33b05b2ac7797df/lib/javassist.jar -------------------------------------------------------------------------------- /lib/junit-4.8.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sgodbillon/BytecodeParser/b24c5c54fe3fa457d79c065de33b05b2ac7797df/lib/junit-4.8.2.jar -------------------------------------------------------------------------------- /lib/log4j-1.2.16.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sgodbillon/BytecodeParser/b24c5c54fe3fa457d79c065de33b05b2ac7797df/lib/log4j-1.2.16.jar -------------------------------------------------------------------------------- /log4j.properties.test.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sgodbillon/BytecodeParser/b24c5c54fe3fa457d79c065de33b05b2ac7797df/log4j.properties.test.jar -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | org.sgodbillon 6 | bytecode-parser 7 | 1.0-SNAPSHOT 8 | jar 9 | 10 | bytecode-parser 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | javassist 20 | javassist 21 | 3.12.1.GA 22 | 23 | 24 | log4j 25 | log4j 26 | 1.2.17 27 | 28 | 29 | junit 30 | junit 31 | 4.8.2 32 | test 33 | 34 | 35 | 36 | 37 | src 38 | src/test 39 | 40 | 41 | 42 | maven-compiler-plugin 43 | 2.3.2 44 | 45 | 1.6 46 | 1.6 47 | 48 | bytecodeparser/** 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/bytecodeparser/CodeParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser; 21 | 22 | import javassist.CtBehavior; 23 | import javassist.bytecode.BadBytecode; 24 | import bytecodeparser.analysis.Opcodes; 25 | import bytecodeparser.analysis.opcodes.Op; 26 | 27 | /** 28 | * A basic bytecode parser. 29 | * @author Stephane Godbillon 30 | * 31 | */ 32 | public class CodeParser { 33 | /** 34 | * The matching context. 35 | */ 36 | public final Context context; 37 | private boolean stop = false; 38 | 39 | public CodeParser(CtBehavior behavior) { 40 | this.context = new Context(behavior); 41 | } 42 | /** 43 | * Parses the bytecode with the given OpHandler. 44 | * @param opHandler 45 | * @throws BadBytecode 46 | * @see {@link OpHandler} 47 | */ 48 | public void parse(OpHandler opHandler) throws BadBytecode { 49 | while(context.iterator.hasNext()) { 50 | if(stop) 51 | break; 52 | int index = context.iterator.next(); 53 | Op op = Opcodes.OPCODES.get(context.iterator.byteAt(index)).init(context, index); 54 | opHandler.handle(op, index); 55 | } 56 | } 57 | 58 | /** 59 | * Moves the code iterator to the given index. 60 | * @param index 61 | */ 62 | public void move(int index) { 63 | stop = false; 64 | context.iterator.move(index); 65 | } 66 | 67 | /** 68 | * Looks the next frame's index. 69 | * @return 70 | */ 71 | public int nextIndex() { 72 | return context.iterator.lookAhead(); 73 | } 74 | 75 | /** 76 | * Resets the code iterator at the beginning of the bytecode. 77 | */ 78 | public void begin() { 79 | stop = false; 80 | context.iterator.begin(); 81 | } 82 | 83 | /** 84 | * Stops the parsing. 85 | */ 86 | public void stop() { 87 | stop = true; 88 | } 89 | } -------------------------------------------------------------------------------- /src/bytecodeparser/Context.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser; 21 | 22 | import java.util.Map; 23 | 24 | import javassist.CtBehavior; 25 | import javassist.NotFoundException; 26 | import javassist.bytecode.ExceptionTable; 27 | import bytecodeparser.analysis.LocalVariable; 28 | 29 | /** 30 | * A context for parsing bytecode. 31 | * @author Stephane Godbillon 32 | * 33 | */ 34 | public class Context { 35 | /** 36 | * The behavior which bytecode is being parsed. 37 | */ 38 | public final CtBehavior behavior; 39 | /** 40 | * The bytecode iterator used for parsing. 41 | */ 42 | public final MultiMarkerCodeIterator iterator; 43 | /** 44 | * The local variables of the behavior. 45 | */ 46 | public final Map localVariables; 47 | /** 48 | * The exception handlers, from the ExceptionTable attribute. 49 | */ 50 | public final int[] exceptionHandlers; 51 | 52 | public Context(CtBehavior behavior, MultiMarkerCodeIterator iterator, Map localVariables) { 53 | this.behavior = behavior; 54 | this.iterator = iterator; 55 | this.localVariables = localVariables; 56 | ExceptionTable exceptionTable = this.behavior.getMethodInfo().getCodeAttribute().getExceptionTable(); 57 | 58 | if(exceptionTable != null) { 59 | this.exceptionHandlers = new int[exceptionTable.size()]; 60 | for(int i = 0; i < exceptionTable.size(); i++) { 61 | exceptionHandlers[i] = exceptionTable.handlerPc(i); 62 | } 63 | } else { 64 | this.exceptionHandlers = new int[0]; 65 | } 66 | } 67 | 68 | public Context(CtBehavior behavior, MultiMarkerCodeIterator iterator) { 69 | this(behavior, iterator, findLocalVariables(behavior)); 70 | } 71 | 72 | public Context(CtBehavior behavior) { 73 | this(behavior, new MultiMarkerCodeIterator(behavior.getMethodInfo().getCodeAttribute()), findLocalVariables(behavior)); 74 | } 75 | 76 | /** 77 | * States if the given index is a start of an exception handler. 78 | * @param index 79 | */ 80 | public boolean isStartOfExceptionHandler(int index) { 81 | for(int i = 0; i < exceptionHandlers.length; i++) 82 | if(exceptionHandlers[i] == index) 83 | return true; 84 | return false; 85 | } 86 | 87 | private static Map findLocalVariables(CtBehavior behavior) { 88 | try { 89 | return LocalVariable.findVariables(behavior); 90 | } catch (NotFoundException e) { 91 | throw new RuntimeException("Error while retrieving the behavior's local variables!", e); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/bytecodeparser/MultiMarkerCodeIterator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser; 21 | 22 | import java.util.ArrayList; 23 | 24 | import javassist.bytecode.CodeAttribute; 25 | import javassist.bytecode.CodeIterator; 26 | 27 | /** 28 | * A code iterator that tracks more than one mark in the bytecode. 29 | * @author Stephane Godbillon 30 | * 31 | */ 32 | public class MultiMarkerCodeIterator extends CodeIterator { 33 | public ArrayList marks = new ArrayList(); 34 | 35 | protected MultiMarkerCodeIterator(CodeAttribute ca) { 36 | super(ca); 37 | } 38 | 39 | @Override 40 | protected void updateCursors(int pos, int length) { 41 | super.updateCursors(pos, length); 42 | for(int i = 0; i < marks.size(); i++) { 43 | int mark = marks.get(i); 44 | if(mark > pos) 45 | marks.set(i, mark + length); 46 | } 47 | } 48 | 49 | /** 50 | * Puts a mark on the given index in the bytecode. 51 | * @param index 52 | * @return the id of this mark, in order to get it later. 53 | */ 54 | public int putMark(int index) { 55 | marks.add(index); 56 | return marks.size() - 1; 57 | } 58 | 59 | /** 60 | * Gets the index in the bytecode tracked by the mark matching the given mark id. 61 | * @param mark the mark id. 62 | * @return the index of this mark. 63 | */ 64 | public int getMark(int mark) { 65 | return marks.get(mark); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/bytecodeparser/OpHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser; 21 | 22 | import bytecodeparser.analysis.opcodes.Op; 23 | 24 | /** 25 | * A handler for opcodes, used when parsing bytecode with the CodeParser. 26 | * @author Stephane Godbillon 27 | * @see CodeParser#parse(OpHandler) 28 | */ 29 | public interface OpHandler { 30 | /** 31 | * Handle the given op at the given index. 32 | * @param op 33 | * @param index 34 | */ 35 | void handle(Op op, int index); 36 | } -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/LocalVariable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis; 21 | 22 | import java.util.HashMap; 23 | import java.util.Map; 24 | import java.util.TreeMap; 25 | 26 | import org.apache.log4j.Logger; 27 | 28 | import javassist.CtBehavior; 29 | import javassist.Modifier; 30 | import javassist.NotFoundException; 31 | import javassist.bytecode.CodeAttribute; 32 | import javassist.bytecode.LocalVariableAttribute; 33 | import bytecodeparser.utils.Utils; 34 | 35 | /** 36 | * A local variable. 37 | * @author Stephane Godbillon 38 | * 39 | */ 40 | public class LocalVariable { 41 | private static final Logger LOGGER = Logger.getLogger(LocalVariable.class); 42 | 43 | /** 44 | * The declaring behavior of this variable. 45 | */ 46 | public final CtBehavior behavior; 47 | /** 48 | * The name of this variable. 49 | */ 50 | public final String name; 51 | /** 52 | * The index of this local variable in the LocalVariableTable attribute. 53 | */ 54 | public final int index; 55 | /** 56 | * The type of this variable. 57 | */ 58 | public final LocalVariableType type; 59 | /** 60 | * Is this local variable a parameter of this behavior? 61 | */ 62 | public final boolean isParameter; 63 | 64 | /** 65 | * Gives the range the local variable is valid within. 66 | */ 67 | public int[] getValidityRange() { 68 | int[] result = new int[2]; 69 | LocalVariableAttribute localVariableAttribute = Utils.getLocalVariableAttribute(behavior); 70 | result[0] = localVariableAttribute.startPc(index); 71 | result[1] = result[0] + localVariableAttribute.codeLength(index); 72 | return result; 73 | } 74 | /** 75 | * The slot the local variable is put into. 76 | * @return 77 | */ 78 | public int getSlot() { 79 | return Utils.getLocalVariableAttribute(behavior).index(index); 80 | } 81 | 82 | public LocalVariable(int index, String name, LocalVariableType type, boolean isParameter, CtBehavior behavior) { 83 | this.index = index; 84 | this.name = name; 85 | this.type = type; 86 | this.behavior = behavior; 87 | this.isParameter = isParameter; 88 | } 89 | @Override 90 | public String toString() { 91 | return name + " (" + type.typeName + ") " + "[" + index + " -> " + getSlot() + "] between [" + getValidityRange()[0] + "," + getValidityRange()[1] + "]"; 92 | } 93 | 94 | /** 95 | * Gets all the local variables of the given behavior, indexed by their index in the LocalVariableTable attribute. 96 | * @param behavior 97 | * @return the local variables of the given behavior, indexed by their index in the LocalVariableTable attribute. 98 | * @throws NotFoundException 99 | */ 100 | public static Map findVariables(CtBehavior behavior) throws NotFoundException { 101 | int nbParameters = behavior.getParameterTypes().length; 102 | boolean isStatic = Modifier.isStatic(behavior.getModifiers()); 103 | Map variables = new HashMap(); 104 | CodeAttribute codeAttribute = behavior.getMethodInfo().getCodeAttribute(); 105 | LocalVariableAttribute localVariableAttribute = (LocalVariableAttribute) codeAttribute.getAttribute("LocalVariableTable"); 106 | LOGGER.debug("search vars : " + localVariableAttribute + " > " + (localVariableAttribute != null ? localVariableAttribute.tableLength() : 0)); 107 | if(localVariableAttribute != null) { 108 | for(int i = 0; i < localVariableAttribute.tableLength(); i++) { 109 | boolean isParameter = isStatic ? i < nbParameters : (i > 0 && i <= nbParameters); 110 | LocalVariable localVariable = new LocalVariable(i, localVariableAttribute.variableName(i), LocalVariableType.parse(localVariableAttribute.signature(i)), isParameter, behavior); 111 | variables.put(i, localVariable); 112 | LOGGER.debug(String.format("findLocalVariables: foud var %s is '%s' (slot %s)", i, localVariable.name, localVariable.getSlot())); 113 | } 114 | } else LOGGER.debug("no local vars found"); 115 | return variables; 116 | } 117 | 118 | /** 119 | * Get the local variable in the given slot at the given index in the given map of local variables. 120 | * @param slot 121 | * @param index 122 | * @param variables 123 | * @return the local variable in the given slot at the given index. 124 | */ 125 | public static LocalVariable getLocalVariable(int slot, int index, Map variables) { 126 | TreeMap variablesByDistance = new TreeMap(); 127 | for(LocalVariable lv : variables.values()) { 128 | if(lv.getSlot() == slot) { 129 | int[] validityRange = lv.getValidityRange(); 130 | if(validityRange[1] >= index) { 131 | if(validityRange[0] <= index) { 132 | LOGGER.debug("getLocalVariable in slot " + slot + " at index " + index + ": found " + lv); 133 | return lv; 134 | } else 135 | variablesByDistance.put(validityRange[0] - index, lv); 136 | } 137 | } 138 | } 139 | if(variablesByDistance.size() > 0) { 140 | LOGGER.debug("getLocalVariable in slot " + slot + " at index " + index + ": found by shorter distance " + variablesByDistance.firstEntry().getValue()); 141 | return variablesByDistance.firstEntry().getValue(); 142 | } 143 | LOGGER.debug("getLocalVariable in slot " + slot + " at index " + index + ": NOT FOUND"); 144 | return null; 145 | } 146 | } -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/LocalVariableType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis; 21 | 22 | import java.util.HashMap; 23 | import java.util.Map; 24 | 25 | import javassist.CtClass; 26 | import javassist.bytecode.Descriptor; 27 | import javassist.bytecode.SignatureAttribute; 28 | import javassist.bytecode.SignatureAttribute.ArrayType; 29 | import javassist.bytecode.SignatureAttribute.ClassType; 30 | 31 | /** 32 | * Information about a localVariable type. 33 | * @author Stephane Godbillon 34 | * 35 | */ 36 | public class LocalVariableType { 37 | /** 38 | * Is it a primitive type (int, long, etc.) 39 | */ 40 | public final boolean isPrimitive; 41 | /** 42 | * The signature of this type. 43 | */ 44 | public final String signature; 45 | /** 46 | * The name of this type, including array info. 47 | * Examples: int, long[], String 48 | */ 49 | public final String typeName; 50 | /** 51 | * The name of this type, without any array info. 52 | * Examples: int, long, String 53 | */ 54 | public final String shortTypeName; 55 | /** 56 | * The dimensions of the array, if any. 57 | * Examples: int => 0, int[][] => 2 58 | */ 59 | public final int dimensions; 60 | 61 | private LocalVariableType(String signature, String typeName, String shortTypeName, boolean isPrimitive, int dimensions) { 62 | this.signature = signature; 63 | this.typeName = typeName; 64 | this.shortTypeName = shortTypeName; 65 | this.isPrimitive = isPrimitive; 66 | this.dimensions = dimensions; 67 | } 68 | 69 | /** 70 | * States if this type is an array. 71 | */ 72 | public boolean isArray() { 73 | return dimensions > 0; 74 | } 75 | 76 | /** 77 | * Makes a localVariableType from a given signature. 78 | * @return LocalVariableType 79 | * @throws RuntimeException if the signature could not be parsed. 80 | */ 81 | public static LocalVariableType parse(String signature) { 82 | int dimensions = 0; 83 | for(int i = 0; i < signature.length(); i++) { 84 | if(signature.charAt(i) == '[') 85 | dimensions++; 86 | else break; 87 | } 88 | try { 89 | javassist.bytecode.SignatureAttribute.Type objectType = SignatureAttribute.toFieldSignature(signature); 90 | if(objectType instanceof ArrayType) 91 | objectType = ((ArrayType) objectType).getComponentType(); 92 | if(objectType instanceof ClassType) { 93 | String typeName = ((ClassType) objectType).getName(); 94 | return new LocalVariableType(signature, addArrayTypeInfo(typeName, dimensions), typeName, false, dimensions); 95 | } 96 | throw new RuntimeException("not a class ?"); 97 | } catch(Exception e) { 98 | // not a class 99 | String typeName = primitiveSymbols.get("" + signature.charAt(dimensions)); 100 | if(typeName == null) 101 | throw new RuntimeException("unknown signature: " + signature, e); 102 | return new LocalVariableType(signature, addArrayTypeInfo(typeName, dimensions), typeName, true, dimensions); 103 | } 104 | } 105 | 106 | /** 107 | * Makes a localVariableType from a given CtClass. 108 | * @return LocalVariableType 109 | */ 110 | public static LocalVariableType from(CtClass clazz) { 111 | return parse(Descriptor.of(clazz)); 112 | } 113 | 114 | private static String addArrayTypeInfo(String typeName, int dimensions) { 115 | String result = typeName; 116 | for(int i = 0; i < dimensions; i++) 117 | result += "[]"; 118 | return result; 119 | } 120 | 121 | private static Map primitiveSymbols = new HashMap(); 122 | static { 123 | primitiveSymbols.put("V", "void"); 124 | primitiveSymbols.put("Z", "boolean"); 125 | primitiveSymbols.put("B", "byte"); 126 | primitiveSymbols.put("C", "char"); 127 | primitiveSymbols.put("S", "short"); 128 | primitiveSymbols.put("I", "int"); 129 | primitiveSymbols.put("J", "long"); 130 | primitiveSymbols.put("F", "float"); 131 | primitiveSymbols.put("D", "double"); 132 | } 133 | } -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/decoders/DecodedArrayCreationOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.decoders; 21 | 22 | import javassist.bytecode.Opcode; 23 | import bytecodeparser.Context; 24 | import bytecodeparser.analysis.opcodes.ArrayCreationOpcode; 25 | import bytecodeparser.analysis.stack.Array; 26 | import bytecodeparser.analysis.stack.Constant.IntegerConstant; 27 | import bytecodeparser.analysis.stack.Stack; 28 | import bytecodeparser.analysis.stack.StackElement; 29 | import bytecodeparser.analysis.stack.TrackableArray; 30 | import bytecodeparser.utils.Utils; 31 | 32 | /** 33 | * A decoded array creation op. 34 | * @author Stephane Godbillon 35 | * 36 | */ 37 | public class DecodedArrayCreationOp extends DecodedBasicOp { 38 | /** 39 | * The number of dimensions of the created array. 40 | */ 41 | public final int dimensions; 42 | /** 43 | * The signature of the created array. 44 | */ 45 | public final String signature; 46 | 47 | public DecodedArrayCreationOp(ArrayCreationOpcode op, Context context, int index) { 48 | super(op, context, index); 49 | if(op.getCode() == Opcode.MULTIANEWARRAY) 50 | dimensions = parameterValues[1]; 51 | else dimensions = 1; 52 | if(op.getCode() == Opcode.NEWARRAY) 53 | signature = getSignatureForSingleDimensionArrayOfPrimitive(parameterValues[0]); 54 | else signature = Utils.getConstPool(context.behavior).getClassInfo(parameterValues[0]); 55 | } 56 | 57 | @Override 58 | public void simulate(Stack stack) { 59 | int size = -1; 60 | if(dimensions == 1) { 61 | StackElement se = stack.pop(); 62 | if(se instanceof IntegerConstant) { 63 | IntegerConstant ic = (IntegerConstant) se; 64 | size = ic.getValue(); 65 | } 66 | } else { 67 | for(int i = 0; i < dimensions; i++) 68 | stack.pop(); 69 | } 70 | if(size > -1) 71 | stack.push(new TrackableArray(signature, size)); 72 | else stack.push(new Array(signature)); 73 | } 74 | 75 | private static String getSignatureForSingleDimensionArrayOfPrimitive(int type) { 76 | switch(type) { 77 | case 4: return "[Z"; 78 | case 5: return "[C"; 79 | case 6: return "[F"; 80 | case 7: return "[D"; 81 | case 8: return "[B"; 82 | case 9: return "[S"; 83 | case 10: return "[I"; 84 | case 11: return "[J"; 85 | default: throw new RuntimeException("unexpected primitive array type! '" + type + "'"); 86 | } 87 | } 88 | 89 | @Override 90 | public String toString() { 91 | return "DecodedArrayCreationOp dimensions=" + dimensions + " signature=" + signature; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/decoders/DecodedArrayOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.decoders; 21 | 22 | import java.util.Arrays; 23 | 24 | import bytecodeparser.Context; 25 | import bytecodeparser.analysis.opcodes.ArrayOpcode; 26 | import bytecodeparser.analysis.stack.Constant.IntegerConstant; 27 | import bytecodeparser.analysis.stack.Stack; 28 | import bytecodeparser.analysis.stack.Stack.StackElementLength; 29 | import bytecodeparser.analysis.stack.StackElement; 30 | import bytecodeparser.analysis.stack.TrackableArray; 31 | 32 | /** 33 | * A decoded array operation op. 34 | * @author Stephane Godbillon 35 | * 36 | */ 37 | public class DecodedArrayOp extends DecodedBasicOp { 38 | public DecodedArrayOp(ArrayOpcode op, Context context, int index) { 39 | super(op, context, index); 40 | } 41 | @Override 42 | public void simulate(Stack stack) { 43 | if(!this.op.as(ArrayOpcode.class).isLoad) { 44 | StackElementLength[] pops = Arrays.copyOf(getPops(), getPops().length - 1); 45 | StackElement subject = stack.getFromTop(StackElementLength.add(pops)); 46 | if(subject instanceof TrackableArray) { 47 | TrackableArray array = (TrackableArray) subject; 48 | StackElement i = stack.getFromTop(StackElementLength.add(array.componentLength)); 49 | if(i instanceof IntegerConstant) { 50 | StackElement value = stack.peek(array.componentLength); 51 | array.set(((IntegerConstant) i).getValue(), value); 52 | } else { 53 | array.isDirty = true; 54 | } 55 | } 56 | } 57 | super.simulate(stack); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/decoders/DecodedBasicOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.decoders; 21 | 22 | import bytecodeparser.Context; 23 | import bytecodeparser.analysis.opcodes.BasicOpcode; 24 | import bytecodeparser.analysis.stack.Stack; 25 | import bytecodeparser.analysis.stack.Stack.StackElementLength; 26 | 27 | /** 28 | * A decoded basic op. 29 | * @author Stephane Godbillon 30 | * 31 | */ 32 | public class DecodedBasicOp extends DecodedOp { 33 | /** 34 | * Pops needed by this decoded op. 35 | */ 36 | public final StackElementLength[] pops; 37 | /** 38 | * Pushes needed by this decoded op. 39 | */ 40 | public final StackElementLength[] pushes; 41 | 42 | public DecodedBasicOp(BasicOpcode op, Context context, int index) { 43 | super(op, context, index); 44 | 45 | this.pops = op.getPops(); 46 | this.pushes = op.getPushes(); 47 | } 48 | 49 | @Override 50 | public void simulate(Stack stack) { 51 | Stack.processBasicAlteration(stack, getPops(), getPushes()); 52 | } 53 | 54 | /** 55 | * Pops needed by this decoded op. 56 | */ 57 | public StackElementLength[] getPops() { 58 | return pops; 59 | } 60 | 61 | /** 62 | * Pushes needed by this decoded op. 63 | */ 64 | public StackElementLength[] getPushes() { 65 | return pushes; 66 | } 67 | } -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/decoders/DecodedBranchOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.decoders; 21 | 22 | import bytecodeparser.Context; 23 | import bytecodeparser.analysis.opcodes.BasicOpcode; 24 | 25 | /** 26 | * A decoded branch op. 27 | * @author Stephane Godbillon 28 | * 29 | */ 30 | public class DecodedBranchOp extends DecodedBasicOp { 31 | private final int jump; 32 | 33 | public DecodedBranchOp(BasicOpcode op, Context context, int index) { 34 | super(op, context, index); 35 | jump = parameterValues[0]; 36 | } 37 | 38 | /** 39 | * @return the index this decoded op will jump to. 40 | */ 41 | public int getJump() { 42 | return jump + index; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/decoders/DecodedConstantPushOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.decoders; 21 | 22 | import java.lang.reflect.Method; 23 | 24 | import javassist.bytecode.ConstPool; 25 | import javassist.bytecode.Opcode; 26 | import bytecodeparser.Context; 27 | import bytecodeparser.analysis.Opcodes.OpParameterType; 28 | import bytecodeparser.analysis.opcodes.ConstantPushOpcode; 29 | import bytecodeparser.analysis.stack.Constant.DoubleConstant; 30 | import bytecodeparser.analysis.stack.Constant.FloatConstant; 31 | import bytecodeparser.analysis.stack.Constant.IntegerConstant; 32 | import bytecodeparser.analysis.stack.Constant.LongConstant; 33 | import bytecodeparser.analysis.stack.Constant.StringConstant; 34 | import bytecodeparser.analysis.stack.Constant.WhateverConstant; 35 | import bytecodeparser.analysis.stack.Stack.StackElementLength; 36 | import bytecodeparser.analysis.stack.Stack; 37 | 38 | /** 39 | * A decoded constant push op. 40 | * @author Stephane Godbillon 41 | * 42 | */ 43 | public class DecodedConstantPushOp extends DecodedBasicOp { 44 | public DecodedConstantPushOp(ConstantPushOpcode op, Context context, int index) { 45 | super(op, context, index); 46 | } 47 | 48 | @Override 49 | public void simulate(Stack stack) { 50 | ConstantPushOpcode cpop = this.op.as(ConstantPushOpcode.class); 51 | if(cpop.getParameterTypes().length == 0) { 52 | switch(cpop.baseCode) { 53 | case Opcode.ICONST_0: 54 | stack.push(new IntegerConstant(cpop.getCode() - cpop.baseCode)); 55 | break; 56 | case Opcode.LCONST_0: 57 | stack.push2(new LongConstant(new Long(new Integer(cpop.getCode() - cpop.baseCode)))); 58 | break; 59 | case Opcode.FCONST_0: 60 | stack.push(new FloatConstant(new Float(cpop.getCode() - cpop.baseCode))); 61 | break; 62 | case Opcode.DCONST_0: 63 | stack.push2(new DoubleConstant(new Double(cpop.getCode() - cpop.baseCode))); 64 | break; 65 | default: 66 | throw new RuntimeException("unsupported basecode=" + cpop.baseCode + "(" + cpop.getName() + ")"); 67 | } 68 | } else { 69 | OpParameterType type = cpop.getParameterTypes()[0]; 70 | int value = cpop.decode(context, index).parameterValues[0]; 71 | if(type == OpParameterType.S1 || type == OpParameterType.S2) { 72 | for(int i = 0; i < getPops().length; i++) { 73 | stack.pop(getPops()[i]); 74 | } 75 | stack.push(new IntegerConstant(cpop.decode(context, index).parameterValues[0])); 76 | } else if(type == OpParameterType.U1 || type == OpParameterType.U2) { 77 | Object o = context.behavior.getMethodInfo().getConstPool().getLdcValue(value); 78 | if(o == null) { 79 | ConstPool cp = context.behavior.getMethodInfo().getConstPool(); 80 | for(Method m : ConstPool.class.getDeclaredMethods()) { 81 | if(m.getName().equals("getItem")) { 82 | m.setAccessible(true); 83 | try { 84 | Object _o = m.invoke(cp, new Integer(value)); 85 | stack.push(new WhateverConstant(_o)); 86 | } catch (Exception e) { 87 | throw new RuntimeException(e); 88 | } 89 | } 90 | } 91 | return; 92 | } 93 | if(pushes[0].equals(StackElementLength.DOUBLE) && !(o instanceof Long) && !(o instanceof Double)) 94 | throw new RuntimeException("Constant push of type " + op.getName() + " should push a double-size element but is not! (o = " + o + ")"); 95 | if(o instanceof Integer) 96 | stack.push(new IntegerConstant((Integer)o)); 97 | else if(o instanceof Long) 98 | stack.push2(new LongConstant((Long)o)); 99 | else if(o instanceof Float) 100 | stack.push(new FloatConstant((Float)o)); 101 | else if(o instanceof Double) 102 | stack.push2(new DoubleConstant((Double)o)); 103 | else if(o instanceof String) 104 | stack.push(new StringConstant((String)o)); 105 | else throw new RuntimeException("unsupported type ??? =" + o.getClass() + "(" + cpop.code + " : " + cpop.getName() + ")"); 106 | } else { 107 | throw new RuntimeException("unsupported code=" + cpop.code + "(" + cpop.getName() + ")"); 108 | } 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/decoders/DecodedFieldOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.decoders; 21 | 22 | import static bytecodeparser.analysis.stack.Stack.StackElementLength.DOUBLE; 23 | import static bytecodeparser.analysis.stack.Stack.StackElementLength.ONE; 24 | import javassist.bytecode.Descriptor; 25 | import javassist.bytecode.Opcode; 26 | import bytecodeparser.Context; 27 | import bytecodeparser.analysis.opcodes.FieldOpcode; 28 | import bytecodeparser.analysis.stack.Stack; 29 | import bytecodeparser.analysis.stack.Stack.StackElementLength; 30 | 31 | /** 32 | * A decoded field operation op. 33 | * @author Stephane Godbillon 34 | * 35 | */ 36 | public class DecodedFieldOp extends DecodedOp { 37 | protected String descriptor; 38 | protected boolean load; 39 | protected boolean isStatic; 40 | protected StackElementLength stackElementLength; 41 | 42 | public DecodedFieldOp(FieldOpcode fo, Context context, int index) { 43 | super(fo, context, index); 44 | String descriptor = context.behavior.getMethodInfo().getConstPool().getFieldrefType(getMethodRefIndex()); 45 | StackElementLength sel = ONE; 46 | if(Descriptor.dataSize(descriptor) == 2) 47 | sel = DOUBLE; 48 | this.stackElementLength = sel; 49 | this.descriptor = descriptor; 50 | this.load = fo.getCode() == Opcode.GETFIELD || fo.getCode() == Opcode.GETSTATIC; 51 | this.isStatic = fo.getCode() == Opcode.GETSTATIC ||fo.getCode() == Opcode.PUTSTATIC; 52 | } 53 | 54 | @Override 55 | public void simulate(Stack stack) { 56 | Stack.processBasicAlteration(stack, getPops(), getPushes()); 57 | } 58 | 59 | /** 60 | * @return the methodRef index of this op. 61 | */ 62 | public int getMethodRefIndex() { 63 | return parameterValues[0]; 64 | } 65 | 66 | /** 67 | * @return the descriptor of the field. 68 | */ 69 | public String getDescriptor() { 70 | return descriptor; 71 | } 72 | 73 | /** 74 | * Pops needed by this decoded op. 75 | */ 76 | public StackElementLength[] getPops() { 77 | if(isStatic && !load) 78 | return new StackElementLength[] { stackElementLength }; 79 | else if(isStatic && load) 80 | return new StackElementLength[0]; 81 | else if(!isStatic && !load) 82 | return new StackElementLength[] { stackElementLength, ONE }; 83 | else return new StackElementLength[] { ONE }; 84 | } 85 | 86 | /** 87 | * Pushes needed by this decoded op. 88 | */ 89 | public StackElementLength[] getPushes() { 90 | if(load) 91 | return new StackElementLength[] { stackElementLength }; 92 | return new StackElementLength[0]; 93 | } 94 | 95 | /** 96 | * States if this op is a read or write operation. 97 | */ 98 | public boolean isRead() { 99 | return load; 100 | } 101 | } -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/decoders/DecodedLocalVariableOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.decoders; 21 | 22 | import javassist.bytecode.Opcode; 23 | 24 | import org.apache.log4j.Logger; 25 | 26 | import bytecodeparser.Context; 27 | import bytecodeparser.analysis.Opcodes.OpParameterType; 28 | import static bytecodeparser.analysis.Opcodes.OpParameterType.*; 29 | import bytecodeparser.analysis.LocalVariable; 30 | import bytecodeparser.analysis.opcodes.LocalVariableOpcode; 31 | import bytecodeparser.analysis.stack.Stack; 32 | import bytecodeparser.analysis.stack.StackElement; 33 | import bytecodeparser.analysis.stack.ValueFromLocalVariable; 34 | 35 | /** 36 | * A decoded local variable operation op. 37 | * @author Stephane Godbillon 38 | * 39 | */ 40 | public class DecodedLocalVariableOp extends DecodedOp { 41 | private static final Logger LOGGER = Logger.getLogger(DecodedLocalVariableOp.class); 42 | /** 43 | * The matching local variable. 44 | */ 45 | public final LocalVariable localVariable; 46 | /** 47 | * States if this op is a read (load) or write (store). 48 | */ 49 | public final boolean load; 50 | /** 51 | * States if the matching localVariable is one- or two-words long. 52 | */ 53 | public final boolean doubleLength; 54 | /** 55 | * States if the op is wide (nb localvars > 256) 56 | */ 57 | public final boolean isWide; 58 | 59 | public DecodedLocalVariableOp(LocalVariableOpcode lvo, Context context, int index, boolean isWide) { 60 | super(lvo, context, index, guessTypes(lvo, context, index, isWide), decodeValues(guessTypes(lvo, context, index, isWide), context.iterator, index + (isWide ? 1 : 0))); 61 | this.isWide = isWide; 62 | int slot; 63 | if(parameterTypes.length > 0) 64 | slot = parameterValues[0]; 65 | else slot = lvo.getCode() - lvo.getBaseOpcode(); 66 | localVariable = LocalVariable.getLocalVariable(slot, index, context.localVariables); 67 | int base = lvo.getBaseOpcode(); 68 | this.load = lvo.isLoad(); 69 | doubleLength = base == Opcode.DLOAD || base == Opcode.DLOAD_0 || base == Opcode.LLOAD || base == Opcode.LLOAD_0 || base == Opcode.DSTORE || base == Opcode.DSTORE_0 || base == Opcode.LSTORE || base == Opcode.LSTORE_0; 70 | } 71 | 72 | @Override 73 | public void simulate(Stack stack) { 74 | if(op.code != Opcode.IINC) { 75 | ValueFromLocalVariable toPush = new ValueFromLocalVariable(localVariable); 76 | if(!load) { 77 | StackElement poppedSe; 78 | if(doubleLength) 79 | poppedSe = stack.pop2(); 80 | else poppedSe = stack.pop(); 81 | /* when a name is null while LocalVariableTable is present, it is likely that this class has been 82 | * previously enhanced and this local variable is just a variable proxy, so grab the original local 83 | * variable and consider its name 84 | */ 85 | if(poppedSe instanceof ValueFromLocalVariable && (localVariable == null || localVariable.name == null)) { 86 | LOGGER.debug("ATTENTION ************** variable proxy for lv = '" + ((ValueFromLocalVariable) poppedSe).localVariable + "'"); 87 | toPush = new ValueFromLocalVariable(((ValueFromLocalVariable) poppedSe).localVariable); 88 | } 89 | } else { 90 | if(doubleLength) 91 | stack.push2(toPush); 92 | else stack.push(toPush); 93 | } 94 | } 95 | } 96 | 97 | private static OpParameterType[] guessTypes(LocalVariableOpcode lvo, Context context, int index, boolean isWide) { 98 | int code = lvo.code; 99 | if(code != Opcode.ALOAD && 100 | code != Opcode.ASTORE && 101 | code != Opcode.DLOAD && 102 | code != Opcode.DSTORE && 103 | code != Opcode.FLOAD && 104 | code != Opcode.FSTORE && 105 | code != Opcode.ILOAD && 106 | code != Opcode.ISTORE && 107 | code != Opcode.LLOAD && 108 | code != Opcode.LSTORE && 109 | code != Opcode.IINC) 110 | return new OpParameterType[0]; 111 | boolean isIINC = lvo.code == Opcode.IINC; 112 | OpParameterType[] result = new OpParameterType[isIINC ? 2 : 1]; 113 | result[0] = isWide ? U2 : U1; 114 | if(isIINC) 115 | result[1] = isWide ? S2 : S1; 116 | return result; 117 | } 118 | } -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/decoders/DecodedOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.decoders; 21 | 22 | import javassist.bytecode.CodeIterator; 23 | import bytecodeparser.Context; 24 | import bytecodeparser.analysis.Opcodes.OpParameterType; 25 | import bytecodeparser.analysis.opcodes.Op; 26 | import bytecodeparser.analysis.stack.Stack; 27 | 28 | /** 29 | * A decoded Op. 30 | * @author Stephane Godbillon 31 | * 32 | */ 33 | public abstract class DecodedOp { 34 | /** 35 | * The context in which this op has been decoded. 36 | */ 37 | public final Context context; 38 | /** 39 | * The index at which this op has been decoded. 40 | */ 41 | public final int index; 42 | /** 43 | * The op that has been decoded. 44 | */ 45 | public final Op op; 46 | 47 | public final OpParameterType[] parameterTypes; 48 | public final int[] parameterValues; 49 | 50 | public DecodedOp(Op op, Context context, int index) { 51 | this(op, context, index, op.getParameterTypes()); 52 | } 53 | 54 | public DecodedOp(Op op, Context context, int index, OpParameterType[] parameterTypes) { 55 | this(op, context, index, parameterTypes, decodeValues(parameterTypes, context.iterator, index)); 56 | } 57 | 58 | public DecodedOp(Op op, Context context, int index, OpParameterType[] parameterTypes, int[] parameterValues) { 59 | this.context = context; 60 | this.index = index; 61 | this.op = op; 62 | this.parameterTypes = parameterTypes; 63 | this.parameterValues = parameterValues; 64 | } 65 | 66 | public static int[] decodeValues(OpParameterType[] parameterTypes, CodeIterator iterator, int index) { 67 | int[] result = new int[parameterTypes.length]; 68 | int nextValIndex = index + 1; 69 | for(int i = 0; i < parameterTypes.length; i++) { 70 | OpParameterType type = parameterTypes[i]; 71 | result[i] = decodeValueAt(type, iterator, nextValIndex); 72 | nextValIndex += type.size; 73 | } 74 | return result; 75 | } 76 | 77 | public static int decodeValueAt(OpParameterType type, CodeIterator iterator, int index) { 78 | switch(type) { 79 | case S1: 80 | return iterator.byteAt(index); 81 | case S2: 82 | return iterator.s16bitAt(index); 83 | case S4: 84 | return iterator.s32bitAt(index); 85 | case U1: 86 | return iterator.byteAt(index); 87 | case U2: 88 | return iterator.u16bitAt(index); 89 | case U4: 90 | default: 91 | throw new RuntimeException("unsupported"); 92 | 93 | } 94 | } 95 | 96 | /** 97 | * Simulate this op onto the given stack. 98 | * @param stack 99 | */ 100 | public abstract void simulate(Stack stack); 101 | } 102 | -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/decoders/DecodedSwitchOpcode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.decoders; 21 | 22 | import static bytecodeparser.analysis.Opcodes.OpParameterType.S4; 23 | 24 | import java.util.Arrays; 25 | 26 | import javassist.bytecode.Opcode; 27 | import bytecodeparser.Context; 28 | import bytecodeparser.analysis.opcodes.SwitchOpcode; 29 | import bytecodeparser.analysis.stack.Stack; 30 | 31 | /** 32 | * A decoded switch (lookup/tableswitch) op. 33 | * @author Stephane Godbillon 34 | * 35 | */ 36 | public class DecodedSwitchOpcode extends DecodedOp { 37 | /** 38 | * The default offset of the switch. 39 | */ 40 | public final int defaultOffset; 41 | /** 42 | * The number of padding bytes, if any. 43 | */ 44 | public final int padding; 45 | /** 46 | * The low index of entries (tableswitch). -1 if lookupswitch. 47 | */ 48 | public final int low; 49 | /** 50 | * The high index of entries (tableswitch). -1 if lookupswitch. 51 | */ 52 | public final int high; 53 | /** 54 | * The number of entries of the switch. 55 | */ 56 | public final int nbEntries; 57 | /** 58 | * The offsets of the entries. 59 | */ 60 | public final int[] offsets; 61 | 62 | public DecodedSwitchOpcode(SwitchOpcode op, Context context, int index) { 63 | super(op, context, index); 64 | int _padding = (index + 1) % 4; 65 | padding = _padding == 0 ? 0 : 4 - _padding; 66 | int nextIndex = index + padding + 1; 67 | defaultOffset = decodeValueAt(S4, context.iterator, nextIndex) + index; 68 | nextIndex += S4.size; 69 | if(op.code == Opcode.TABLESWITCH) { 70 | low = decodeValueAt(S4, context.iterator, nextIndex); 71 | nextIndex += S4.size; 72 | high = decodeValueAt(S4, context.iterator, nextIndex); 73 | nextIndex += S4.size; 74 | nbEntries = high - low + 1; 75 | offsets = new int[nbEntries]; 76 | for(int i = 0; i < offsets.length; i++) { 77 | offsets[i] = decodeValueAt(S4, context.iterator, nextIndex) + index; 78 | nextIndex += S4.size; 79 | } 80 | } else { // LOOKUPSWITCH 81 | low = high = -1; 82 | nbEntries = decodeValueAt(S4, context.iterator, nextIndex); 83 | nextIndex += S4.size; 84 | offsets = new int[nbEntries]; 85 | for(int i = 0; i < offsets.length; i++) { 86 | nextIndex += S4.size; 87 | offsets[i] = decodeValueAt(S4, context.iterator, nextIndex) + index; 88 | nextIndex += S4.size; 89 | } 90 | } 91 | } 92 | 93 | @Override 94 | public void simulate(Stack stack) { 95 | stack.pop(); 96 | } 97 | 98 | @Override 99 | public String toString() { 100 | return "DecodedSwitchOpcode [" + op.getName() + "] : redirects -> " + Arrays.toString(offsets) + ", default " + defaultOffset + "(high=" + high + ", low=" + low + ")"; 101 | } 102 | } -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/decoders/DecodedWideOp.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.decoders; 21 | 22 | import bytecodeparser.Context; 23 | import bytecodeparser.analysis.Opcodes; 24 | import bytecodeparser.analysis.opcodes.LocalVariableOpcode; 25 | import bytecodeparser.analysis.opcodes.WideOpcode; 26 | import bytecodeparser.analysis.stack.Stack; 27 | 28 | /** 29 | * A decoded wide local variable operation op. 30 | * @author Stephane Godbillon 31 | * 32 | */ 33 | public class DecodedWideOp extends DecodedOp { 34 | /** 35 | * The wrapped decoded local variable opcode. 36 | */ 37 | public final DecodedLocalVariableOp wrappedDecodedLocalVariableOp; 38 | 39 | public DecodedWideOp(WideOpcode wide, Context context, int index) { 40 | super(wide, context, index); 41 | wrappedDecodedLocalVariableOp = Opcodes.OPCODES.get(context.iterator.byteAt(index + 1)).as(LocalVariableOpcode.class).decodeWide(context, index); 42 | } 43 | 44 | @Override 45 | public void simulate(Stack stack) { 46 | wrappedDecodedLocalVariableOp.simulate(stack); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/opcodes/ArrayCreationOpcode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.opcodes; 21 | 22 | import bytecodeparser.Context; 23 | import bytecodeparser.analysis.Opcodes.OpParameterType; 24 | import bytecodeparser.analysis.decoders.DecodedArrayCreationOp; 25 | 26 | /** 27 | * An array creation opcode. 28 | * @author Stephane Godbillon 29 | * 30 | */ 31 | public class ArrayCreationOpcode extends BasicOpcode { 32 | public ArrayCreationOpcode(int code, OpParameterType... opParameterTypes) { 33 | super(code, opParameterTypes); 34 | } 35 | @Override 36 | public DecodedArrayCreationOp decode(Context context, int index) { 37 | return new DecodedArrayCreationOp(this, context, index); 38 | } 39 | } -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/opcodes/ArrayOpcode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.opcodes; 21 | 22 | import bytecodeparser.Context; 23 | import bytecodeparser.analysis.Opcodes.OpParameterType; 24 | import bytecodeparser.analysis.decoders.DecodedArrayOp; 25 | 26 | /** 27 | * An opcode that is an operation on an array. 28 | * @author Stephane Godbillon 29 | * 30 | */ 31 | public class ArrayOpcode extends BasicOpcode { 32 | /** 33 | * States if the operation is a read (load -> true) or a write (store -> false). 34 | */ 35 | public final boolean isLoad; 36 | 37 | public ArrayOpcode(int code, boolean isLoad, OpParameterType... opParameterTypes) { 38 | super(code, opParameterTypes); 39 | this.isLoad = isLoad; 40 | } 41 | 42 | @Override 43 | public DecodedArrayOp decode(Context context, int index) { 44 | return new DecodedArrayOp(this, context, index); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/opcodes/BasicOpcode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.opcodes; 21 | 22 | import bytecodeparser.Context; 23 | import bytecodeparser.analysis.Opcodes.OpParameterType; 24 | import bytecodeparser.analysis.decoders.DecodedBasicOp; 25 | import bytecodeparser.analysis.stack.Stack.StackElementLength; 26 | 27 | /** 28 | * A basic op that performs classic push/pops on the stack. 29 | * @author Stephane Godbillon 30 | * 31 | */ 32 | public class BasicOpcode extends Op { 33 | protected StackElementLength[] pops, pushes; 34 | public BasicOpcode(int code, OpParameterType... opParameterTypes) { 35 | this(code, new StackElementLength[0], new StackElementLength[0], opParameterTypes); 36 | } 37 | public BasicOpcode(int code, StackElementLength[] pops, StackElementLength[] pushes, OpParameterType... opParameterTypes) { 38 | super(code, opParameterTypes); 39 | this.pops = pops; 40 | this.pushes = pushes; 41 | } 42 | /** 43 | * @return the pops of this opcode. 44 | */ 45 | public StackElementLength[] getPops() { 46 | return pops; 47 | } 48 | /** 49 | * @return the pushes of this opcode. 50 | */ 51 | public StackElementLength[] getPushes() { 52 | return pushes; 53 | } 54 | @Override 55 | public DecodedBasicOp decode(Context context, int index) { 56 | return new DecodedBasicOp(this, context, index); 57 | } 58 | @Override 59 | public String toString() { 60 | return "BasicOp: " + getName(); 61 | } 62 | /** 63 | * Internal use only. 64 | */ 65 | public BasicOpcode setPops(StackElementLength... pops) { 66 | if(pops != null) 67 | this.pops = pops; 68 | return this; 69 | } 70 | /** 71 | * Internal use only. 72 | */ 73 | public BasicOpcode setPushes(StackElementLength... pushes) { 74 | if(pushes != null) 75 | this.pushes = pushes; 76 | return this; 77 | } 78 | } -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/opcodes/BranchOpCode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.opcodes; 21 | 22 | import javassist.bytecode.Opcode; 23 | import bytecodeparser.Context; 24 | import bytecodeparser.analysis.Opcodes.OpParameterType; 25 | import bytecodeparser.analysis.decoders.DecodedBranchOp; 26 | import bytecodeparser.analysis.stack.Stack.StackElementLength; 27 | 28 | /** 29 | * An opcode that stands for a fork in the bytecode. 30 | * @author Stephane Godbillon 31 | * 32 | */ 33 | public class BranchOpCode extends BasicOpcode { 34 | public BranchOpCode(int code, OpParameterType... opParameterTypes) { 35 | super(code, opParameterTypes); 36 | } 37 | public BranchOpCode(int code, StackElementLength[] pops, StackElementLength[] pushes, OpParameterType... opParameterTypes) { 38 | super(code, pops, pushes, opParameterTypes); 39 | } 40 | 41 | @Override 42 | public DecodedBranchOp decode(Context context, int index) { 43 | return new DecodedBranchOp(this, context, index); 44 | } 45 | 46 | /** 47 | * States if this opcode is conditional fork or not. 48 | */ 49 | public boolean isConditional() { 50 | return code >= Opcode.IFEQ && code <= Opcode.IF_ACMPNE || code == Opcode.IFNULL || code == Opcode.IFNONNULL; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/opcodes/ConstantPushOpcode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.opcodes; 21 | 22 | import bytecodeparser.Context; 23 | import bytecodeparser.analysis.Opcodes.OpParameterType; 24 | import bytecodeparser.analysis.decoders.DecodedConstantPushOp; 25 | 26 | /** 27 | * An opcode that stands for a push of a constant onto the stack. 28 | * @author Stephane Godbillon 29 | * 30 | */ 31 | public class ConstantPushOpcode extends BasicOpcode { 32 | public final int baseCode; 33 | 34 | public ConstantPushOpcode(int code, OpParameterType... opParameterTypes) { 35 | this(code, code, opParameterTypes); 36 | } 37 | 38 | public ConstantPushOpcode(int code, int baseCode, OpParameterType... opParameterTypes) { 39 | super(code, opParameterTypes); 40 | this.baseCode = baseCode; 41 | } 42 | 43 | @Override 44 | public DecodedConstantPushOp decode(Context context, int index) { 45 | return new DecodedConstantPushOp(this, context, index); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/opcodes/ExitOpcode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.opcodes; 21 | 22 | import bytecodeparser.analysis.Opcodes.OpParameterType; 23 | import bytecodeparser.analysis.stack.Stack.StackElementLength; 24 | 25 | /** 26 | * An opcode that stands for an exit of the behavior (like a return). 27 | * @author Stephane Godbillon 28 | * 29 | */ 30 | public class ExitOpcode extends BasicOpcode { 31 | public ExitOpcode(int code, OpParameterType... opParameterTypes) { 32 | super(code, opParameterTypes); 33 | } 34 | public ExitOpcode(int code, StackElementLength[] pops, StackElementLength[] pushes, OpParameterType... opParameterTypes) { 35 | super(code, pops, pushes, opParameterTypes); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/opcodes/FieldOpcode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.opcodes; 21 | 22 | import static bytecodeparser.analysis.Opcodes.OpParameterType.U2; 23 | import bytecodeparser.Context; 24 | import bytecodeparser.analysis.decoders.DecodedFieldOp; 25 | 26 | /** 27 | * An opcode concerning a field (read, write). 28 | * @author Stephane Godbillon 29 | * 30 | */ 31 | public class FieldOpcode extends Op { 32 | private final DecodedFieldOp decodedOp; 33 | 34 | public FieldOpcode(int code) { 35 | this(code, null); 36 | } 37 | private FieldOpcode(int code, DecodedFieldOp decodedOp) { 38 | super(code, U2); 39 | this.decodedOp = decodedOp; 40 | } 41 | @Override 42 | public FieldOpcode init(Context context, int index) { 43 | return new FieldOpcode(code, decode(context, index)); 44 | } 45 | @Override 46 | public DecodedFieldOp decode(Context context, int index) { 47 | if(decodedOp != null) 48 | return decodedOp; 49 | try { 50 | DecodedFieldOp decodedOp = new DecodedFieldOp(this, context, index); 51 | return decodedOp; 52 | } catch (Exception e) { 53 | throw new RuntimeException(e); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/opcodes/LocalVariableOpcode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.opcodes; 21 | 22 | import bytecodeparser.Context; 23 | import bytecodeparser.analysis.decoders.DecodedLocalVariableOp; 24 | 25 | /** 26 | * An opcode concerning a local variable (read, write). 27 | * @author Stephane Godbillon 28 | * 29 | */ 30 | public class LocalVariableOpcode extends Op { 31 | private final int base; 32 | private final boolean load; 33 | 34 | public LocalVariableOpcode(int code, boolean load) { 35 | this(code, code, load); 36 | } 37 | public LocalVariableOpcode(int code, int base, boolean load) { 38 | super(code); 39 | this.base = base; 40 | this.load = load; 41 | } 42 | 43 | @Override 44 | public DecodedLocalVariableOp decode(Context context, int index) { 45 | return new DecodedLocalVariableOp(this, context, index, false); 46 | } 47 | 48 | public DecodedLocalVariableOp decodeWide(Context context, int index) { 49 | return new DecodedLocalVariableOp(this, context, index, true); 50 | } 51 | 52 | public int getBaseOpcode() { 53 | return base; 54 | } 55 | 56 | /** 57 | * States if this opcode is a read (load -> true) or a write (store -> false). 58 | * @return 59 | */ 60 | public boolean isLoad() { 61 | return load; 62 | } 63 | 64 | @Override 65 | public String toString() { 66 | return "LocalVariableOp: " + getName(); 67 | } 68 | } -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/opcodes/MethodInvocationOpcode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.opcodes; 21 | 22 | import static bytecodeparser.analysis.Opcodes.OpParameterType.U2; 23 | import javassist.bytecode.Opcode; 24 | import bytecodeparser.Context; 25 | import bytecodeparser.analysis.decoders.DecodedMethodInvocationOp; 26 | 27 | /** 28 | * An opcode that stands for a method invocation. 29 | * @author Stephane Godbillon 30 | * 31 | */ 32 | public class MethodInvocationOpcode extends Op { 33 | public MethodInvocationOpcode(int code) { 34 | super(code, U2); 35 | } 36 | /** 37 | * States if the invoked method is static or not. 38 | */ 39 | public boolean isInstanceMethod() { 40 | return code != Opcode.INVOKESTATIC; 41 | } 42 | @Override 43 | public DecodedMethodInvocationOp decode(Context context, int index) { 44 | try { 45 | return new DecodedMethodInvocationOp(this, context, index); 46 | } catch (Exception e) { 47 | throw new RuntimeException(e); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/opcodes/Op.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.opcodes; 21 | 22 | import bytecodeparser.Context; 23 | import bytecodeparser.analysis.Opcodes; 24 | import bytecodeparser.analysis.Opcodes.OpParameterType; 25 | import bytecodeparser.analysis.decoders.DecodedOp; 26 | 27 | public abstract class Op { 28 | /** 29 | * The opcode int. 30 | */ 31 | public final int code; 32 | protected final OpParameterType[] parameterTypes; 33 | private String name; 34 | public Op(int code, OpParameterType... opParameterTypes) { 35 | this.code = code; 36 | this.parameterTypes = opParameterTypes; 37 | } 38 | 39 | /** 40 | * Decodes this op with a given context. 41 | * @param context 42 | * @param index 43 | * @return the matching decodedOp. 44 | */ 45 | public abstract DecodedOp decode(Context context, int index); 46 | 47 | /** 48 | * Should be called before using this object. 49 | * @return this object's copy with some contextual information, if needed. 50 | */ 51 | public Op init(Context context, int index) { 52 | return this; 53 | } 54 | 55 | /** 56 | * @return the opcode int. 57 | */ 58 | public int getCode() { 59 | return code; 60 | } 61 | 62 | /** 63 | * @return the paramaters types of this op, if any. 64 | */ 65 | public OpParameterType[] getParameterTypes() { 66 | return parameterTypes; 67 | } 68 | 69 | /** 70 | * @return the name of this opcode. 71 | */ 72 | public String getName() { 73 | if(name == null) 74 | name = Opcodes.findOpName(code); 75 | return name; 76 | } 77 | 78 | /** 79 | * Shortcut for chaining and casting. 80 | * @param specificOpClass 81 | * @return the casted op. 82 | */ 83 | @SuppressWarnings(value="unchecked") 84 | public T as(Class specificOpClass) { 85 | return (T) this; 86 | } 87 | 88 | @Override 89 | public String toString() { 90 | return "op: " + getName() + ""; 91 | } 92 | } -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/opcodes/SwitchOpcode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.opcodes; 21 | 22 | import bytecodeparser.Context; 23 | import bytecodeparser.analysis.decoders.DecodedSwitchOpcode; 24 | 25 | /** 26 | * LookupSwitch or TableSwitch opcode. 27 | * @author Stephane Godbillon 28 | * 29 | */ 30 | public class SwitchOpcode extends Op { 31 | 32 | public SwitchOpcode(int code) { 33 | super(code); 34 | } 35 | 36 | @Override 37 | public DecodedSwitchOpcode decode(Context context, int index) { 38 | return new DecodedSwitchOpcode(this, context, index); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/opcodes/WideOpcode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.opcodes; 21 | 22 | import bytecodeparser.Context; 23 | import bytecodeparser.analysis.decoders.DecodedLocalVariableOp; 24 | import bytecodeparser.analysis.decoders.DecodedWideOp; 25 | import javassist.bytecode.Opcode; 26 | 27 | /** 28 | * Wide opcode for localvariables (if there is more than 256 local vars in the method's body). 29 | * @author Stephane Godbillon 30 | * 31 | */ 32 | public class WideOpcode extends Op { 33 | private final DecodedWideOp decodedWideOp; 34 | 35 | public WideOpcode() { 36 | this(null); 37 | } 38 | 39 | private WideOpcode(DecodedWideOp decodedWideOp) { 40 | super(Opcode.WIDE); 41 | this.decodedWideOp = decodedWideOp; 42 | } 43 | 44 | @Override 45 | public Op init(Context context, int index) { 46 | return new WideOpcode(new DecodedWideOp(this, context, index)); 47 | } 48 | 49 | @Override 50 | public DecodedWideOp decode(Context context, int index) { 51 | if(decodedWideOp != null) 52 | return decodedWideOp; 53 | throw new RuntimeException("must be initialized before !"); 54 | } 55 | 56 | /** 57 | * Gets the wrapped localVariable opcode. 58 | * This op MUST be decoded before invoking this method. 59 | * @return the wrapped localVariable op. 60 | * @throws RuntimeException if this op has not been initialized with init(context, index) before. 61 | */ 62 | public LocalVariableOpcode getWrappedLocalVariableOpcode() { 63 | if(decodedWideOp != null) 64 | return decodedWideOp.op.as(LocalVariableOpcode.class); 65 | throw new RuntimeException("must be initialized before !"); 66 | } 67 | 68 | /** 69 | * Gets the wrapped decoded localVariable opcode. 70 | * This op MUST be decoded before invoking this method. 71 | * @return the wrapped decoded localVariable op. 72 | * @throws RuntimeException if this op has not been initialized with init(context, index) before. 73 | */ 74 | public DecodedLocalVariableOp getWrappedDecodedLocalVariableOp() { 75 | if(decodedWideOp != null) 76 | return decodedWideOp.wrappedDecodedLocalVariableOp; 77 | throw new RuntimeException("must be initialized before !"); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/stack/Array.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.stack; 21 | 22 | /** 23 | * A StackElement that stands for an array. 24 | * @author Stephane Godbillon 25 | * 26 | */ 27 | public class Array extends StackElement { 28 | /** 29 | * The signature of this array. 30 | */ 31 | public final String signature; 32 | public Array(String signature) { 33 | this.signature = signature; 34 | } 35 | @Override 36 | public Array copy() { 37 | return new Array(signature); 38 | } 39 | @Override 40 | public String toString() { 41 | return "simple array of '" + signature + "'"; 42 | } 43 | } -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/stack/Constant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.stack; 21 | 22 | /** 23 | * A StackElement that is a constant. 24 | * 25 | * @author Stephane Godbillon 26 | * 27 | * @param T can be one of : String, Integer, Float, Long, Double, or Object. See the subclasses for more information. 28 | */ 29 | public abstract class Constant extends StackElement { 30 | protected final T value; 31 | 32 | public Constant(T value) { 33 | this.value = value; 34 | } 35 | 36 | /** 37 | * @return The wrapped value. 38 | */ 39 | public T getValue() { 40 | return value; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return this.getClass().getSimpleName() + ": " + value; 46 | } 47 | 48 | /** 49 | * A StackElement that stands for a String Constant. 50 | * @author Stephane Godbillon 51 | * 52 | */ 53 | public static class StringConstant extends Constant { 54 | public StringConstant(String value) { 55 | super(value); 56 | } 57 | @Override 58 | public StackElement copy() { 59 | return new StringConstant(value); 60 | } 61 | } 62 | 63 | /** 64 | * A StackElement that stands for an Integer Constant. 65 | * @author Stephane Godbillon 66 | * 67 | */ 68 | public static class IntegerConstant extends Constant { 69 | public IntegerConstant(Integer value) { 70 | super(value); 71 | } 72 | @Override 73 | public StackElement copy() { 74 | return new IntegerConstant(value); 75 | } 76 | } 77 | 78 | /** 79 | * A StackElement that stands for a Float Constant. 80 | * @author Stephane Godbillon 81 | * 82 | */ 83 | public static class FloatConstant extends Constant { 84 | public FloatConstant(Float value) { 85 | super(value); 86 | } 87 | @Override 88 | public StackElement copy() { 89 | return new FloatConstant(value); 90 | } 91 | } 92 | 93 | /** 94 | * A StackElement that stands for a Long Constant. 95 | * @author Stephane Godbillon 96 | * 97 | */ 98 | public static class LongConstant extends Constant { 99 | public LongConstant(Long value) { 100 | super(value); 101 | } 102 | @Override 103 | public StackElement copy() { 104 | return new LongConstant(value); 105 | } 106 | } 107 | 108 | /** 109 | * A StackElement that stands for a Double Constant. 110 | * @author Stephane Godbillon 111 | * 112 | */ 113 | public static class DoubleConstant extends Constant { 114 | public DoubleConstant(Double value) { 115 | super(value); 116 | } 117 | @Override 118 | public StackElement copy() { 119 | return new DoubleConstant(value); 120 | } 121 | } 122 | 123 | /** 124 | * A StackElement that stands for an Object Constant (so, whatever constant...). 125 | * @author Stephane Godbillon 126 | * 127 | */ 128 | public static class WhateverConstant extends Constant { 129 | public WhateverConstant(Object value) { 130 | super(value); 131 | } 132 | @Override 133 | public StackElement copy() { 134 | return new WhateverConstant(value); 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/stack/Stack.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.stack; 21 | 22 | import static bytecodeparser.analysis.stack.Stack.StackElementLength.DOUBLE; 23 | 24 | import java.util.LinkedList; 25 | 26 | import org.apache.log4j.Logger; 27 | 28 | /** 29 | * Represents the current stack's state. 30 | * 31 | * @author Stephane Godbillon 32 | * 33 | */ 34 | public class Stack { 35 | private static final Logger LOGGER = Logger.getLogger(Stack.class); 36 | 37 | /** 38 | * Length of a stack element. Can be one or two words. 39 | * @author Stephane Godbillon 40 | * 41 | */ 42 | public static enum StackElementLength { 43 | /** 44 | * One word length 45 | */ 46 | ONE, // one word 47 | /** 48 | * Two words length 49 | */ 50 | DOUBLE; // two words 51 | 52 | /** 53 | * Computes the total length of the stackElementLengths. 54 | * @param stackElementLengths 55 | * @return The total length of the stackElementLengths. 56 | */ 57 | public static int add(StackElementLength... stackElementLengths) { 58 | int result = 0; 59 | for(StackElementLength sel : stackElementLengths) { 60 | result += sel == ONE ? 1 : 2; 61 | } 62 | return result; 63 | } 64 | } 65 | 66 | /** 67 | * Linked List holding the references of this stack's elements. 68 | * It is preferable to use the methods of this class instead of accessing this field. 69 | */ 70 | public LinkedList stack = new LinkedList(); 71 | 72 | /** 73 | * States if this stack is empty. 74 | * @return true if this stack is empty, false if not. 75 | */ 76 | public boolean isEmpty() { 77 | return stack.size() == 0; 78 | } 79 | 80 | /** 81 | * Removes the top stackElement from this stack. 82 | * The stackElement must be one-word length. 83 | * @throws java.util.NoSuchElementException if this stack is empty. 84 | * @throws RuntimeException if the stackElement is a part of a two-words element. 85 | * @return the removed stackElement. 86 | */ 87 | public StackElement pop() { 88 | StackElement se = stack.pop(); 89 | if(se instanceof TOP) 90 | throw new RuntimeException("WARN: popped a TOP!"); 91 | return se; 92 | } 93 | 94 | /** 95 | * Removes the top stackElement from this stack. 96 | * The stackElement must be two-words length. 97 | * @throws java.util.NoSuchElementException if this stack is empty. 98 | * @throws RuntimeException if the stackElement is not a two-words element. 99 | * @return the removed stackElement. 100 | */ 101 | public StackElement pop2() { 102 | StackElement se = stack.pop(); 103 | if( !(se instanceof TOP) ) 104 | throw new RuntimeException("WARN: popped2 top is not a TOP! (is instanceof " + se.getClass() + ")"); 105 | se = stack.pop(); 106 | if(se instanceof TOP) 107 | throw new RuntimeException("WARN: popped2 a TOP!"); 108 | return se; 109 | } 110 | 111 | /** 112 | * Removes the top stackElement of the given length from this stack. 113 | * @throws java.util.NoSuchElementException if this stack is empty. 114 | * @throws RuntimeException if the top stackElement is not of the given length. 115 | * @return the removed stackElement. 116 | */ 117 | public StackElement pop(StackElementLength length) { 118 | if(length == StackElementLength.DOUBLE) 119 | return pop2(); 120 | return pop(); 121 | } 122 | 123 | /** 124 | * Returns the top stackElement from this stack. 125 | * The stackElement might be a a TOP (part of a two-words element). 126 | * @throws java.util.NoSuchElementException if this stack is empty. 127 | * @return the stackElement. 128 | */ 129 | public StackElement peek() { 130 | StackElement se = stack.peek(); 131 | if(se instanceof TOP) 132 | LOGGER.warn("WARN: popped a TOP!"); 133 | return se; 134 | } 135 | 136 | /** 137 | * Returns the top-1 stackElement from this stack. 138 | * The stackElement might be a a TOP (part of a two-words element). 139 | * @throws java.util.NoSuchElementException if this stack is empty. 140 | * @return the stackElement. 141 | */ 142 | public StackElement peek2() { 143 | StackElement se = stack.get(stack.size() - 2); 144 | if(se instanceof TOP) 145 | LOGGER.warn("WARN: peek2 a TOP!"); 146 | return se; 147 | } 148 | 149 | /** 150 | * Returns the top or top-1 stackElement from this stack, depending on the given length. 151 | * The stackElement might be a a TOP (part of a two-words element). 152 | * @throws java.util.NoSuchElementException if this stack is empty. 153 | * @return the stackElement. 154 | */ 155 | public StackElement peek(StackElementLength length) { 156 | if(length == StackElementLength.DOUBLE) 157 | return peek2(); 158 | return peek(); 159 | } 160 | 161 | /** 162 | * Pushes the given one-word stackElement on the stack. 163 | * @param se The element to push on. 164 | * @return the current Stack instance for chaining. 165 | */ 166 | public Stack push(StackElement se) { 167 | stack.push(se); 168 | return this; 169 | } 170 | 171 | /** 172 | * Pushes the given two-words stackElement on the stack. 173 | * @param se The element to push on. 174 | * @return the current Stack instance for chaining. 175 | */ 176 | public Stack push2(StackElement se) { 177 | stack.push(se); 178 | stack.push(new TOP()); 179 | return this; 180 | } 181 | 182 | /** 183 | * Get the n-ith element from the stack. 184 | * @param i 185 | * @return the stackElement. Can be a TOP (part of a two-words element). 186 | */ 187 | public StackElement getFromTop(int i) { 188 | return stack.get(i); 189 | } 190 | 191 | /** 192 | * Makes a copy of this Stack instance. 193 | * @return a new Stack instance containing the same elements. 194 | */ 195 | public Stack copy() { 196 | Stack copy = new Stack(); 197 | copy.stack = new LinkedList(this.stack); 198 | return copy; 199 | } 200 | 201 | @Override 202 | public String toString() { 203 | StringBuffer sb = new StringBuffer("stack: ["); 204 | for(int i = 0; i < stack.size(); i++) { 205 | if(i > 0) 206 | sb.append(", "); 207 | sb.append(stack.get(i)); 208 | } 209 | return sb.append("]").toString(); 210 | } 211 | 212 | /** 213 | * Pops some elements from the given stack, then pushes some Whatever elements onto it. 214 | * @param stack 215 | * @param pops 216 | * @param pushes 217 | */ 218 | // TODO 219 | public static void processBasicAlteration(Stack stack, StackElementLength[] pops, StackElementLength[] pushes) { 220 | for(int i = 0; i < pops.length; i++) { 221 | if(pops[i] == DOUBLE) 222 | stack.pop2(); 223 | else stack.pop(); 224 | } 225 | for(int i = 0; i < pushes.length; i++) { 226 | if(pushes[i] == DOUBLE) 227 | stack.push2(new Whatever()); 228 | else stack.push(new Whatever()); 229 | } 230 | } 231 | } -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/stack/StackElement.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.stack; 21 | 22 | /** 23 | * A Stack Element. 24 | * @author Stephane Godbillon 25 | * 26 | */ 27 | public abstract class StackElement { 28 | /** 29 | * @return a copy of this StackElement. 30 | */ 31 | public abstract StackElement copy(); 32 | @Override public String toString() { 33 | return this.getClass().toString(); 34 | } 35 | } -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/stack/TOP.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.stack; 21 | 22 | /** 23 | * A StackElement that is a part of a two-words Element. 24 | * @author Stephane Godbillon 25 | * 26 | */ 27 | public class TOP extends StackElement { 28 | @Override 29 | public StackElement copy() { 30 | return new TOP(); 31 | } 32 | @Override 33 | public String toString() { 34 | return "TOP"; 35 | } 36 | } -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/stack/TrackableArray.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.stack; 21 | 22 | import java.util.Arrays; 23 | 24 | import org.apache.log4j.Logger; 25 | 26 | import bytecodeparser.analysis.stack.Stack.StackElementLength; 27 | 28 | /** 29 | * A trackable Array is an array of known elements at compile time: its content can be "guessed" by the analyzer. 30 | * When this array gets updated with a value that is unknown at compile-time, this value is an instance of WhateverElement. 31 | * 32 | * This is particularly useful to guess the names of the varargs, for example. 33 | * 34 | * If a trackable array contains some elements that cannot be guessed 35 | * 36 | * @author Stephane Godbillon 37 | * 38 | */ 39 | public class TrackableArray extends Array { 40 | private static final Logger LOGGER = Logger.getLogger(TrackableArray.class); 41 | 42 | /** 43 | * The StackElements of this array. 44 | */ 45 | public final StackElement[] elements; 46 | /** 47 | * The length of each component. 48 | */ 49 | public final StackElementLength componentLength; 50 | public boolean isDirty; 51 | public TrackableArray(String signature, int size) { 52 | this(signature, makeNewArray(size), parseSignature(signature)); 53 | } 54 | public TrackableArray(String signature, StackElement[] elements, StackElementLength componentLength) { 55 | super(signature); 56 | this.elements = elements; 57 | this.componentLength = componentLength; 58 | } 59 | @Override 60 | public Array copy() { 61 | return this; 62 | } 63 | public TrackableArray set(int i, StackElement element) { 64 | LOGGER.trace("in trackable array, set " + i + " => " + element); 65 | elements[i] = element; 66 | return this; 67 | } 68 | @Override 69 | public String toString() { 70 | return "TrackableArray of '" + signature + "'"; 71 | } 72 | private static StackElement[] makeNewArray(int size) { 73 | StackElement[] result = new StackElement[size]; 74 | Arrays.fill(result, new VoidElement()); 75 | return result; 76 | } 77 | 78 | private static StackElementLength parseSignature(String signature) { 79 | return StackElementLength.ONE; 80 | } 81 | } -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/stack/ValueFromLocalVariable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.stack; 21 | 22 | import bytecodeparser.analysis.LocalVariable; 23 | 24 | /** 25 | * A StackElement representing a value that was read from a localVariable (so the value may be known at this time). 26 | * @author Stephane Godbillon 27 | * 28 | */ 29 | public class ValueFromLocalVariable extends StackElement { 30 | /** 31 | * The local variable from which this value was read. 32 | */ 33 | public final LocalVariable localVariable; 34 | public ValueFromLocalVariable(LocalVariable localVariable) { 35 | this.localVariable = localVariable; 36 | } 37 | @Override 38 | public StackElement copy() { 39 | return new ValueFromLocalVariable(localVariable); 40 | } 41 | 42 | @Override 43 | public String toString() { 44 | return "ValueFromLocalVariable '" + (localVariable != null ? localVariable.name : "NONAME") + "'"; 45 | } 46 | } -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/stack/VoidElement.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.stack; 21 | 22 | public class VoidElement extends StackElement { 23 | @Override 24 | public StackElement copy() { 25 | return new VoidElement(); 26 | } 27 | @Override 28 | public String toString() { 29 | return "Void"; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/bytecodeparser/analysis/stack/Whatever.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.analysis.stack; 21 | 22 | /** 23 | * A StackElement of something we don't know anything about at compile-time. 24 | * @author Stephane Godbillon 25 | * 26 | */ 27 | public class Whatever extends StackElement { 28 | @Override 29 | public StackElement copy() { 30 | return new Whatever(); 31 | } 32 | @Override 33 | public String toString() { 34 | return "Whatever"; 35 | } 36 | } -------------------------------------------------------------------------------- /src/bytecodeparser/utils/Utils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package bytecodeparser.utils; 21 | 22 | import javassist.CtBehavior; 23 | import javassist.bytecode.ConstPool; 24 | import javassist.bytecode.ExceptionTable; 25 | import javassist.bytecode.LineNumberAttribute; 26 | import javassist.bytecode.LocalVariableAttribute; 27 | 28 | public class Utils { 29 | /** 30 | * Gets the LocalVariableAttribute of the behavior. 31 | * @param behavior 32 | * @throws NullPointerException if this behavior has no code attribute. 33 | * @return the LocalVariableAttribute or null if none. 34 | */ 35 | public static LocalVariableAttribute getLocalVariableAttribute(CtBehavior behavior) { 36 | return (LocalVariableAttribute) behavior.getMethodInfo().getCodeAttribute().getAttribute("LocalVariableTable"); 37 | } 38 | 39 | /** 40 | * Gets the LineNumberAttribute of the behavior. 41 | * @param behavior 42 | * @throws NullPointerException if this behavior has no code attribute. 43 | * @return the LineNumberAttribute or null if none. 44 | */ 45 | public static LineNumberAttribute getLineNumberAttribute(CtBehavior behavior) { 46 | return (LineNumberAttribute) behavior.getMethodInfo().getCodeAttribute().getAttribute("LineNumberTable"); 47 | } 48 | 49 | /** 50 | * Gets the constpool attribute of this behavior. 51 | * @param behavior 52 | * @return the constpool attribute of this behavior or null if none. 53 | */ 54 | public static ConstPool getConstPool(CtBehavior behavior) { 55 | return behavior.getMethodInfo().getConstPool(); 56 | } 57 | 58 | public static void debugExceptionTable(ExceptionTable et, ConstPool cp) { 59 | for(int i = 0; i < et.size(); i++) { 60 | System.out.println(et.startPc(i) + " -> " + et.endPc(i) + " : " + et.handlerPc(i) + ", type=" + (et.catchType(i) != 0 ? cp.getClassInfo(et.catchType(i)) : "any")); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/test/CommonTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package test; 21 | 22 | import java.util.Arrays; 23 | 24 | import javassist.ClassPool; 25 | import javassist.CtClass; 26 | import javassist.CtMethod; 27 | import javassist.NotFoundException; 28 | import bytecodeparser.Context; 29 | import bytecodeparser.analysis.decoders.DecodedMethodInvocationOp; 30 | import bytecodeparser.analysis.stack.StackAnalyzer.Frame; 31 | import bytecodeparser.analysis.stack.StackElement; 32 | import bytecodeparser.analysis.stack.TOP; 33 | import bytecodeparser.analysis.stack.TrackableArray; 34 | import bytecodeparser.analysis.stack.ValueFromLocalVariable; 35 | 36 | public class CommonTests { 37 | public static CtClass getCtClass(String clazz) { 38 | ClassPool cp = ClassPool.getDefault(); 39 | try { 40 | return cp.get(clazz); 41 | } catch (NotFoundException e) { 42 | throw new RuntimeException(e); 43 | } 44 | } 45 | 46 | public static CtMethod getMethod(CtClass ctClass, String name) { 47 | for(CtMethod ctMethod : ctClass.getMethods()) { 48 | if(ctMethod.getName().equals(name)) { 49 | return ctMethod; 50 | } 51 | } 52 | throw new RuntimeException("method '" + name + "' not found in class " + ctClass); 53 | } 54 | 55 | public static void assertDeepEquals(String[] array1, String[] array2) { 56 | if(array1.length != array2.length) 57 | throw new RuntimeException(Arrays.toString(array1) + " does not equal " + Arrays.toString(array2) + " !"); 58 | for(int i = 0; i < array1.length; i++) 59 | if(array1[i] != array2[i] && (array1[i] == null || !array1[i].equals(array2[i])) ) 60 | throw new RuntimeException(Arrays.toString(array1) + " does not equal " + Arrays.toString(array2) + " !"); 61 | } 62 | 63 | // old 64 | 65 | private static String getLocalVariableName(StackElement se) { 66 | if(se instanceof ValueFromLocalVariable) { 67 | ValueFromLocalVariable v = (ValueFromLocalVariable) se; 68 | if(v.localVariable != null) 69 | return v.localVariable.name; 70 | } 71 | return null; 72 | } 73 | 74 | public static String getMethodNamedSignature(Context context, Frame frame) { 75 | DecodedMethodInvocationOp decoded = (DecodedMethodInvocationOp) frame.decodedOp; 76 | String name = decoded.getName(); 77 | String[] names = DecodedMethodInvocationOp.resolveParametersNames(frame, true); 78 | StringBuffer sb = new StringBuffer(); 79 | if(names.length > 0) { 80 | sb.append(names[0]); 81 | for(int i = 1; i < names.length; i++) { 82 | sb.append(", ").append(names[i]); 83 | } 84 | } 85 | sb.insert(0, "(").insert(0, name).append(")"); 86 | return sb.toString(); 87 | } 88 | 89 | public static String[] methodInvocationNames(Frame frame) { 90 | DecodedMethodInvocationOp decoded = (DecodedMethodInvocationOp) frame.decodedOp; 91 | int nbParams = decoded.getNbParameters(); 92 | String[] result = new String[nbParams]; 93 | if(nbParams > 0) { 94 | int stackIndex = 0; 95 | if(frame.stackBefore.stack.get(stackIndex) instanceof TrackableArray) { 96 | StackElement[] varargs = ((TrackableArray) frame.stackBefore.stack.get(0)).elements; 97 | nbParams = nbParams + varargs.length - 1; 98 | result = new String[nbParams]; 99 | for(int i = 0; i < varargs.length; i++, nbParams--) { 100 | result[nbParams - 1] = getLocalVariableName(varargs[i]) + "(" + varargs[i] + ")"; 101 | } 102 | stackIndex++; 103 | } 104 | while(nbParams > 0) { 105 | StackElement se = frame.stackBefore.stack.get(stackIndex++); 106 | if(se instanceof TOP) 107 | se = frame.stackBefore.stack.get(stackIndex++); 108 | result[nbParams - 1] = getLocalVariableName(se) + "(" + se + ")"; 109 | nbParams--; 110 | } 111 | } 112 | return result; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/test/coucou.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sgodbillon/BytecodeParser/b24c5c54fe3fa457d79c065de33b05b2ac7797df/src/test/coucou.yml -------------------------------------------------------------------------------- /src/test/subjects/Common.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package test.subjects; 21 | 22 | public class Common { 23 | public static void classic(String s, int i, long j) { } 24 | public static void varargs(int... integers) { } 25 | public static void mixed(String s, long j, int... integers) { } 26 | public static void mixed2(double d, int... integers) { } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/subjects/SimpleSubjects.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package test.subjects; 21 | 22 | import static test.subjects.Common.*; 23 | 24 | public class SimpleSubjects { 25 | public void simple() { 26 | int myInt = 89; 27 | long date = System.currentTimeMillis(); 28 | String subject = "test"; 29 | classic(subject, myInt, date); 30 | classic(null, 0, date); 31 | classic("", 1, 2L); 32 | } 33 | 34 | public void simpleWithParams(String s1, int i1) { 35 | int myInt = 89; 36 | long date = System.currentTimeMillis(); 37 | String subject = "test"; 38 | classic(subject, myInt, date); 39 | classic(null, 0, date); 40 | classic("", 1, 2L); 41 | } 42 | 43 | public void simpleWithConditionals(String s1, int i1) { 44 | int myInt = 89; 45 | long date = System.currentTimeMillis(); 46 | String subject = "test"; 47 | if(i1 > 0) { 48 | myInt = 90; 49 | int myInt2 = myInt + 1; 50 | classic(subject, myInt2, date); 51 | } 52 | classic(null, 0, date); 53 | classic("", 1, 2L); 54 | } 55 | 56 | public void varargs() { 57 | int myInt = 89; 58 | int myInt2 = 99; 59 | long date = System.currentTimeMillis(); 60 | String subject = "test"; 61 | Common.varargs(); 62 | Common.varargs(myInt, 3, myInt2); 63 | Common.varargs(1); 64 | Common.mixed(subject, date); 65 | Common.mixed(subject, date, myInt); 66 | Common.mixed(subject, date, myInt, 1); 67 | Common.mixed(subject, date, 1); 68 | } 69 | 70 | public void exceptions() { 71 | int myInt = 89; 72 | long date = System.currentTimeMillis(); 73 | try { 74 | String subject = "test"; 75 | classic(subject, myInt, date); 76 | } catch(Exception e) { 77 | classic(null, 0, date); 78 | } finally { 79 | classic("", 1, 2L); 80 | } 81 | } 82 | 83 | public void tableswitchBlock(int switcher) { 84 | int myInt = 89; 85 | long date = System.currentTimeMillis(); 86 | String subject = "test"; 87 | switch(switcher) { 88 | case 1: 89 | classic(subject, myInt, date); 90 | break; 91 | case 2: 92 | classic(null, 0, date); 93 | break; 94 | case 3: 95 | classic("", 1, 2L); 96 | break; 97 | } 98 | } 99 | 100 | public void lookupswitchBlock(int switcher) { 101 | int myInt = 89; 102 | long date = System.currentTimeMillis(); 103 | String subject = "test"; 104 | switch(switcher) { 105 | case 1: 106 | classic(subject, myInt, date); 107 | break; 108 | case 2: 109 | classic(null, 0, date); 110 | break; 111 | case 7: 112 | classic("", 1, 2L); 113 | break; 114 | } 115 | } 116 | 117 | public void multinewarray() { 118 | int[][] integers = new int[2][5]; 119 | String[][][] strings = new String[5][6][7]; 120 | integers[1][4] = 555; 121 | long[] longs = new long[66]; 122 | String[] simpleStrings = new String[2]; 123 | simpleStrings[1] = strings[1][2][3] = "toto"; 124 | longs[1] = 4669292874L; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/test/subjects/Subject.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Stephane Godbillon 3 | * 4 | * This file is part of BytecodeParser. See the README file in the root 5 | * directory of this project. 6 | * 7 | * BytecodeParser is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Lesser General Public License as published by 9 | * the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | 12 | * BytecodeParser is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Lesser General Public License for more details. 16 | 17 | * You should have received a copy of the GNU Lesser General Public License 18 | * along with BytecodeParser. If not, see . 19 | */ 20 | package test.subjects; 21 | 22 | public class Subject { 23 | public String subj = "subj"; 24 | public void say(String smth) { 25 | int i; 26 | i = 15; 27 | int j = 0; 28 | int k = j + i; 29 | try { 30 | System.out.println(k); 31 | } catch(Exception e) { 32 | System.out.println("b"); 33 | } finally { 34 | System.out.println("finally"); 35 | } 36 | /*if(j == 0) 37 | throw new RuntimeException("yop");*/ 38 | smth.length(); 39 | for(long l = 0; l < 6; l++) { 40 | String t = "truc" + l; 41 | System.out.println(t); 42 | };i++; 43 | java.util.Date dd = new java.util.Date(); 44 | Subject subject = new Subject(); 45 | subject.subj = "koko"; 46 | try { 47 | dd.toString(); 48 | i++; 49 | } catch(RuntimeException e) { 50 | System.out.println(e); 51 | } 52 | 53 | String name = "truc"; 54 | String name2 = "truc2"; 55 | String[] names = new String[] { "y1", "y2" }; 56 | long toto = 398738947098720L; 57 | Object object__ = new Object(); 58 | machin("kbce", name2, names, x6(toto), object__); 59 | process(toto, "a", "b"); 60 | processStatic("c", "d"); 61 | String ff = "ff"; 62 | process(toto, ff); 63 | } 64 | 65 | static int hehe = 0; 66 | public static String hello() { 67 | try { 68 | try { 69 | String bidule = "bidule"; 70 | System.out.println(bidule); 71 | return bidule; 72 | } catch (RuntimeException e) { 73 | throw new RuntimeException(e); 74 | } catch (Exception e) { 75 | throw new RuntimeException(e); 76 | } finally { 77 | "trc".length(); 78 | } 79 | } catch(Exception e) { 80 | throw new RuntimeException(e); 81 | } 82 | } 83 | 84 | public void machin(String coucou, String bidule, String[] chponk, long toto, Object o) { 85 | 86 | } 87 | 88 | public void process(long t, String...strings) { 89 | // blob 90 | } 91 | 92 | public static void processStatic(String...strings) { 93 | 94 | } 95 | 96 | public void truc() { 97 | int i = 0; 98 | i = i + 1; 99 | } 100 | 101 | public long x6(long i) { 102 | return i * 6; 103 | } 104 | /* 105 | read :: 9 -> smth 106 | read :: 11 -> s 107 | write :: 6 -> i 108 | write :: 7 -> j 109 | write :: 8 -> k 110 | write :: 10 -> s 111 | */ 112 | } 113 | --------------------------------------------------------------------------------