summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/bytecode/BytecodeTools.java
diff options
context:
space:
mode:
authorGravatar jeff2015-01-13 23:25:04 -0500
committerGravatar jeff2015-01-13 23:25:04 -0500
commit959cb5fd4f9586ec3bd265b452fe25fe1db82e3f (patch)
treebdd8a2c52c2fe053ba3460614bde8542e5378dbe /src/cuchaz/enigma/bytecode/BytecodeTools.java
parentgot rid of gradle in favor of ivy+ssjb (diff)
downloadenigma-fork-959cb5fd4f9586ec3bd265b452fe25fe1db82e3f.tar.gz
enigma-fork-959cb5fd4f9586ec3bd265b452fe25fe1db82e3f.tar.xz
enigma-fork-959cb5fd4f9586ec3bd265b452fe25fe1db82e3f.zip
source format change
don't hate me too much if you were planning a big merge. =P
Diffstat (limited to 'src/cuchaz/enigma/bytecode/BytecodeTools.java')
-rw-r--r--src/cuchaz/enigma/bytecode/BytecodeTools.java269
1 files changed, 115 insertions, 154 deletions
diff --git a/src/cuchaz/enigma/bytecode/BytecodeTools.java b/src/cuchaz/enigma/bytecode/BytecodeTools.java
index 4407a90..2e456f4 100644
--- a/src/cuchaz/enigma/bytecode/BytecodeTools.java
+++ b/src/cuchaz/enigma/bytecode/BytecodeTools.java
@@ -34,256 +34,222 @@ import cuchaz.enigma.Util;
34import cuchaz.enigma.bytecode.BytecodeIndexIterator.Index; 34import cuchaz.enigma.bytecode.BytecodeIndexIterator.Index;
35import cuchaz.enigma.bytecode.accessors.ConstInfoAccessor; 35import cuchaz.enigma.bytecode.accessors.ConstInfoAccessor;
36 36
37public class BytecodeTools 37public class BytecodeTools {
38{ 38
39 public static byte[] writeBytecode( Bytecode bytecode ) 39 public static byte[] writeBytecode(Bytecode bytecode) throws IOException {
40 throws IOException 40
41 {
42 ByteArrayOutputStream buf = new ByteArrayOutputStream(); 41 ByteArrayOutputStream buf = new ByteArrayOutputStream();
43 DataOutputStream out = new DataOutputStream( buf ); 42 DataOutputStream out = new DataOutputStream(buf);
44 try 43
45 { 44 try {
46 // write the constant pool 45 // write the constant pool
47 new ConstPoolEditor( bytecode.getConstPool() ).writePool( out ); 46 new ConstPoolEditor(bytecode.getConstPool()).writePool(out);
48 47
49 // write metadata 48 // write metadata
50 out.writeShort( bytecode.getMaxStack() ); 49 out.writeShort(bytecode.getMaxStack());
51 out.writeShort( bytecode.getMaxLocals() ); 50 out.writeShort(bytecode.getMaxLocals());
52 out.writeShort( bytecode.getStackDepth() ); 51 out.writeShort(bytecode.getStackDepth());
53 52
54 // write the code 53 // write the code
55 out.writeShort( bytecode.getSize() ); 54 out.writeShort(bytecode.getSize());
56 out.write( bytecode.get() ); 55 out.write(bytecode.get());
57 56
58 // write the exception table 57 // write the exception table
59 int numEntries = bytecode.getExceptionTable().size(); 58 int numEntries = bytecode.getExceptionTable().size();
60 out.writeShort( numEntries ); 59 out.writeShort(numEntries);
61 for( int i=0; i<numEntries; i++ ) 60 for (int i = 0; i < numEntries; i++) {
62 { 61 out.writeShort(bytecode.getExceptionTable().startPc(i));
63 out.writeShort( bytecode.getExceptionTable().startPc( i ) ); 62 out.writeShort(bytecode.getExceptionTable().endPc(i));
64 out.writeShort( bytecode.getExceptionTable().endPc( i ) ); 63 out.writeShort(bytecode.getExceptionTable().handlerPc(i));
65 out.writeShort( bytecode.getExceptionTable().handlerPc( i ) ); 64 out.writeShort(bytecode.getExceptionTable().catchType(i));
66 out.writeShort( bytecode.getExceptionTable().catchType( i ) );
67 } 65 }
68 66
69 out.close(); 67 out.close();
70 return buf.toByteArray(); 68 return buf.toByteArray();
71 } 69 } catch (Exception ex) {
72 catch( Exception ex ) 70 Util.closeQuietly(out);
73 { 71 throw new Error(ex);
74 Util.closeQuietly( out );
75 throw new Error( ex );
76 } 72 }
77 } 73 }
78 74
79 public static Bytecode readBytecode( byte[] bytes ) 75 public static Bytecode readBytecode(byte[] bytes) throws IOException {
80 throws IOException 76
81 { 77 ByteArrayInputStream buf = new ByteArrayInputStream(bytes);
82 ByteArrayInputStream buf = new ByteArrayInputStream( bytes ); 78 DataInputStream in = new DataInputStream(buf);
83 DataInputStream in = new DataInputStream( buf ); 79
84 try 80 try {
85 {
86 // read the constant pool entries and update the class 81 // read the constant pool entries and update the class
87 ConstPool pool = ConstPoolEditor.readPool( in ); 82 ConstPool pool = ConstPoolEditor.readPool(in);
88 83
89 // read metadata 84 // read metadata
90 int maxStack = in.readShort(); 85 int maxStack = in.readShort();
91 int maxLocals = in.readShort(); 86 int maxLocals = in.readShort();
92 int stackDepth = in.readShort(); 87 int stackDepth = in.readShort();
93 88
94 Bytecode bytecode = new Bytecode( pool, maxStack, maxLocals ); 89 Bytecode bytecode = new Bytecode(pool, maxStack, maxLocals);
95 bytecode.setStackDepth( stackDepth ); 90 bytecode.setStackDepth(stackDepth);
96 91
97 // read the code 92 // read the code
98 int size = in.readShort(); 93 int size = in.readShort();
99 byte[] code = new byte[size]; 94 byte[] code = new byte[size];
100 in.read( code ); 95 in.read(code);
101 setBytecode( bytecode, code ); 96 setBytecode(bytecode, code);
102 97
103 // read the exception table 98 // read the exception table
104 int numEntries = in.readShort(); 99 int numEntries = in.readShort();
105 for( int i=0; i<numEntries; i++ ) 100 for (int i = 0; i < numEntries; i++) {
106 { 101 bytecode.getExceptionTable().add(in.readShort(), in.readShort(), in.readShort(), in.readShort());
107 bytecode.getExceptionTable().add( in.readShort(), in.readShort(), in.readShort(), in.readShort() );
108 } 102 }
109 103
110 in.close(); 104 in.close();
111 return bytecode; 105 return bytecode;
112 } 106 } catch (Exception ex) {
113 catch( Exception ex ) 107 Util.closeQuietly(in);
114 { 108 throw new Error(ex);
115 Util.closeQuietly( in );
116 throw new Error( ex );
117 } 109 }
118 } 110 }
119 111
120 public static Bytecode prepareMethodForBytecode( CtBehavior behavior, Bytecode bytecode ) 112 public static Bytecode prepareMethodForBytecode(CtBehavior behavior, Bytecode bytecode) throws BadBytecode {
121 throws BadBytecode 113
122 {
123 // update the destination class const pool 114 // update the destination class const pool
124 bytecode = copyBytecodeToConstPool( behavior.getMethodInfo().getConstPool(), bytecode ); 115 bytecode = copyBytecodeToConstPool(behavior.getMethodInfo().getConstPool(), bytecode);
125 116
126 // update method locals and stack 117 // update method locals and stack
127 CodeAttribute attribute = behavior.getMethodInfo().getCodeAttribute(); 118 CodeAttribute attribute = behavior.getMethodInfo().getCodeAttribute();
128 if( bytecode.getMaxLocals() > attribute.getMaxLocals() ) 119 if (bytecode.getMaxLocals() > attribute.getMaxLocals()) {
129 { 120 attribute.setMaxLocals(bytecode.getMaxLocals());
130 attribute.setMaxLocals( bytecode.getMaxLocals() );
131 } 121 }
132 if( bytecode.getMaxStack() > attribute.getMaxStack() ) 122 if (bytecode.getMaxStack() > attribute.getMaxStack()) {
133 { 123 attribute.setMaxStack(bytecode.getMaxStack());
134 attribute.setMaxStack( bytecode.getMaxStack() );
135 } 124 }
136 125
137 return bytecode; 126 return bytecode;
138 } 127 }
139 128
140 public static Bytecode copyBytecodeToConstPool( ConstPool dest, Bytecode bytecode ) 129 public static Bytecode copyBytecodeToConstPool(ConstPool dest, Bytecode bytecode) throws BadBytecode {
141 throws BadBytecode 130
142 {
143 // get the entries this bytecode needs from the const pool 131 // get the entries this bytecode needs from the const pool
144 Set<Integer> indices = Sets.newTreeSet(); 132 Set<Integer> indices = Sets.newTreeSet();
145 ConstPoolEditor editor = new ConstPoolEditor( bytecode.getConstPool() ); 133 ConstPoolEditor editor = new ConstPoolEditor(bytecode.getConstPool());
146 BytecodeIndexIterator iterator = new BytecodeIndexIterator( bytecode ); 134 BytecodeIndexIterator iterator = new BytecodeIndexIterator(bytecode);
147 for( Index index : iterator.indices() ) 135 for (Index index : iterator.indices()) {
148 { 136 assert (index.isValid(bytecode));
149 assert( index.isValid( bytecode ) ); 137 InfoType.gatherIndexTree(indices, editor, index.getIndex());
150 InfoType.gatherIndexTree( indices, editor, index.getIndex() );
151 } 138 }
152 139
153 Map<Integer,Integer> indexMap = Maps.newTreeMap(); 140 Map<Integer,Integer> indexMap = Maps.newTreeMap();
154 141
155 ConstPool src = bytecode.getConstPool(); 142 ConstPool src = bytecode.getConstPool();
156 ConstPoolEditor editorSrc = new ConstPoolEditor( src ); 143 ConstPoolEditor editorSrc = new ConstPoolEditor(src);
157 ConstPoolEditor editorDest = new ConstPoolEditor( dest ); 144 ConstPoolEditor editorDest = new ConstPoolEditor(dest);
158 145
159 // copy entries over in order of level so the index mapping is easier 146 // copy entries over in order of level so the index mapping is easier
160 for( InfoType type : InfoType.getSortedByLevel() ) 147 for (InfoType type : InfoType.getSortedByLevel()) {
161 { 148 for (int index : indices) {
162 for( int index : indices ) 149 ConstInfoAccessor entry = editorSrc.getItem(index);
163 {
164 ConstInfoAccessor entry = editorSrc.getItem( index );
165 150
166 // skip entries that aren't this type 151 // skip entries that aren't this type
167 if( entry.getType() != type ) 152 if (entry.getType() != type) {
168 {
169 continue; 153 continue;
170 } 154 }
171 155
172 // make sure the source entry is valid before we copy it 156 // make sure the source entry is valid before we copy it
173 assert( type.subIndicesAreValid( entry, editorSrc ) ); 157 assert (type.subIndicesAreValid(entry, editorSrc));
174 assert( type.selfIndexIsValid( entry, editorSrc ) ); 158 assert (type.selfIndexIsValid(entry, editorSrc));
175 159
176 // make a copy of the entry so we can modify it safely 160 // make a copy of the entry so we can modify it safely
177 ConstInfoAccessor entryCopy = editorSrc.getItem( index ).copy(); 161 ConstInfoAccessor entryCopy = editorSrc.getItem(index).copy();
178 assert( type.subIndicesAreValid( entryCopy, editorSrc ) ); 162 assert (type.subIndicesAreValid(entryCopy, editorSrc));
179 assert( type.selfIndexIsValid( entryCopy, editorSrc ) ); 163 assert (type.selfIndexIsValid(entryCopy, editorSrc));
180 164
181 // remap the indices 165 // remap the indices
182 type.remapIndices( indexMap, entryCopy ); 166 type.remapIndices(indexMap, entryCopy);
183 assert( type.subIndicesAreValid( entryCopy, editorDest ) ); 167 assert (type.subIndicesAreValid(entryCopy, editorDest));
184 168
185 // put the copy in the destination pool 169 // put the copy in the destination pool
186 int newIndex = editorDest.addItem( entryCopy.getItem() ); 170 int newIndex = editorDest.addItem(entryCopy.getItem());
187 entryCopy.setIndex( newIndex ); 171 entryCopy.setIndex(newIndex);
188 assert( type.selfIndexIsValid( entryCopy, editorDest ) ) : type + ", self: " + entryCopy + " dest: " + editorDest.getItem( entryCopy.getIndex() ); 172 assert (type.selfIndexIsValid(entryCopy, editorDest)) : type + ", self: " + entryCopy + " dest: " + editorDest.getItem(entryCopy.getIndex());
189 173
190 // make sure the source entry is unchanged 174 // make sure the source entry is unchanged
191 assert( type.subIndicesAreValid( entry, editorSrc ) ); 175 assert (type.subIndicesAreValid(entry, editorSrc));
192 assert( type.selfIndexIsValid( entry, editorSrc ) ); 176 assert (type.selfIndexIsValid(entry, editorSrc));
193 177
194 // add the index mapping so we can update the bytecode later 178 // add the index mapping so we can update the bytecode later
195 if( indexMap.containsKey( index ) ) 179 if (indexMap.containsKey(index)) {
196 { 180 throw new Error("Entry at index " + index + " already copied!");
197 throw new Error( "Entry at index " + index + " already copied!" );
198 } 181 }
199 indexMap.put( index, newIndex ); 182 indexMap.put(index, newIndex);
200 } 183 }
201 } 184 }
202 185
203 // make a new bytecode 186 // make a new bytecode
204 Bytecode newBytecode = new Bytecode( dest, bytecode.getMaxStack(), bytecode.getMaxLocals() ); 187 Bytecode newBytecode = new Bytecode(dest, bytecode.getMaxStack(), bytecode.getMaxLocals());
205 bytecode.setStackDepth( bytecode.getStackDepth() ); 188 bytecode.setStackDepth(bytecode.getStackDepth());
206 setBytecode( newBytecode, bytecode.get() ); 189 setBytecode(newBytecode, bytecode.get());
207 setExceptionTable( newBytecode, bytecode.getExceptionTable() ); 190 setExceptionTable(newBytecode, bytecode.getExceptionTable());
208 191
209 // apply the mappings to the bytecode 192 // apply the mappings to the bytecode
210 BytecodeIndexIterator iter = new BytecodeIndexIterator( newBytecode ); 193 BytecodeIndexIterator iter = new BytecodeIndexIterator(newBytecode);
211 for( Index index : iter.indices() ) 194 for (Index index : iter.indices()) {
212 {
213 int oldIndex = index.getIndex(); 195 int oldIndex = index.getIndex();
214 Integer newIndex = indexMap.get( oldIndex ); 196 Integer newIndex = indexMap.get(oldIndex);
215 if( newIndex != null ) 197 if (newIndex != null) {
216 {
217 // make sure this mapping makes sense 198 // make sure this mapping makes sense
218 InfoType typeSrc = editorSrc.getItem( oldIndex ).getType(); 199 InfoType typeSrc = editorSrc.getItem(oldIndex).getType();
219 InfoType typeDest = editorDest.getItem( newIndex ).getType(); 200 InfoType typeDest = editorDest.getItem(newIndex).getType();
220 assert( typeSrc == typeDest ); 201 assert (typeSrc == typeDest);
221 202
222 // apply the mapping 203 // apply the mapping
223 index.setIndex( newIndex ); 204 index.setIndex(newIndex);
224 } 205 }
225 } 206 }
226 iter.saveChangesToBytecode(); 207 iter.saveChangesToBytecode();
227 208
228 // make sure all the indices are valid 209 // make sure all the indices are valid
229 iter = new BytecodeIndexIterator( newBytecode ); 210 iter = new BytecodeIndexIterator(newBytecode);
230 for( Index index : iter.indices() ) 211 for (Index index : iter.indices()) {
231 { 212 assert (index.isValid(newBytecode));
232 assert( index.isValid( newBytecode ) );
233 } 213 }
234 214
235 return newBytecode; 215 return newBytecode;
236 } 216 }
237 217
238 public static void setBytecode( Bytecode dest, byte[] src ) 218 public static void setBytecode(Bytecode dest, byte[] src) {
239 { 219 if (src.length > dest.getSize()) {
240 if( src.length > dest.getSize() ) 220 dest.addGap(src.length - dest.getSize());
241 {
242 dest.addGap( src.length - dest.getSize() );
243 } 221 }
244 assert( dest.getSize() == src.length ); 222 assert (dest.getSize() == src.length);
245 for( int i=0; i<src.length; i++ ) 223 for (int i = 0; i < src.length; i++) {
246 { 224 dest.write(i, src[i]);
247 dest.write( i, src[i] );
248 } 225 }
249 } 226 }
250 227
251 public static void setExceptionTable( Bytecode dest, ExceptionTable src ) 228 public static void setExceptionTable(Bytecode dest, ExceptionTable src) {
252 { 229
253 // clear the dest exception table 230 // clear the dest exception table
254 int size = dest.getExceptionTable().size(); 231 int size = dest.getExceptionTable().size();
255 for( int i=size-1; i>=0; i-- ) 232 for (int i = size - 1; i >= 0; i--) {
256 { 233 dest.getExceptionTable().remove(i);
257 dest.getExceptionTable().remove( i );
258 } 234 }
259 235
260 // copy the exception table 236 // copy the exception table
261 for( int i=0; i<src.size(); i++ ) 237 for (int i = 0; i < src.size(); i++) {
262 { 238 dest.getExceptionTable().add(src.startPc(i), src.endPc(i), src.handlerPc(i), src.catchType(i));
263 dest.getExceptionTable().add(
264 src.startPc( i ),
265 src.endPc( i ),
266 src.handlerPc( i ),
267 src.catchType( i )
268 );
269 } 239 }
270 } 240 }
271 241
272 public static List<String> getParameterTypes( String signature ) 242 public static List<String> getParameterTypes(String signature) {
273 {
274 List<String> types = Lists.newArrayList(); 243 List<String> types = Lists.newArrayList();
275 for( int i=0; i<signature.length(); ) 244 for (int i = 0; i < signature.length();) {
276 { 245 char c = signature.charAt(i);
277 char c = signature.charAt( i );
278 246
279 // handle parens 247 // handle parens
280 if( c == '(' ) 248 if (c == '(') {
281 {
282 i++; 249 i++;
283 c = signature.charAt( i ); 250 c = signature.charAt(i);
284 } 251 }
285 if( c == ')' ) 252 if (c == ')') {
286 {
287 break; 253 break;
288 } 254 }
289 255
@@ -291,35 +257,30 @@ public class BytecodeTools
291 String type = null; 257 String type = null;
292 258
293 int arrayDim = 0; 259 int arrayDim = 0;
294 while( c == '[' ) 260 while (c == '[') {
295 {
296 // advance to array type 261 // advance to array type
297 arrayDim++; 262 arrayDim++;
298 i++; 263 i++;
299 c = signature.charAt( i ); 264 c = signature.charAt(i);
300 } 265 }
301 266
302 if( c == 'L' ) 267 if (c == 'L') {
303 {
304 // read class type 268 // read class type
305 int pos = signature.indexOf( ';', i + 1 ); 269 int pos = signature.indexOf(';', i + 1);
306 String className = signature.substring( i + 1, pos ); 270 String className = signature.substring(i + 1, pos);
307 type = "L" + className + ";"; 271 type = "L" + className + ";";
308 i = pos + 1; 272 i = pos + 1;
309 } 273 } else {
310 else
311 {
312 // read primitive type 274 // read primitive type
313 type = signature.substring( i, i + 1 ); 275 type = signature.substring(i, i + 1);
314 i++; 276 i++;
315 } 277 }
316 278
317 // was it an array? 279 // was it an array?
318 while( arrayDim-- > 0 ) 280 while (arrayDim-- > 0) {
319 {
320 type = "[" + type; 281 type = "[" + type;
321 } 282 }
322 types.add( type ); 283 types.add(type);
323 } 284 }
324 return types; 285 return types;
325 } 286 }