summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/bytecode/BytecodeIndexIterator.java
diff options
context:
space:
mode:
authorGravatar jeff2014-07-27 22:33:21 -0400
committerGravatar jeff2014-07-27 22:33:21 -0400
commitd7321b5b0d38c575e54c770f7aa18dacbacab3c8 (patch)
treeef4b3e0f83b1fe89125c2674fec023871e70c0d8 /src/cuchaz/enigma/bytecode/BytecodeIndexIterator.java
parentmade gui responsive to caret position and show identifier info (diff)
downloadenigma-fork-d7321b5b0d38c575e54c770f7aa18dacbacab3c8.tar.gz
enigma-fork-d7321b5b0d38c575e54c770f7aa18dacbacab3c8.tar.xz
enigma-fork-d7321b5b0d38c575e54c770f7aa18dacbacab3c8.zip
added identifier renaming capability
copied some code over from M3L to handle the heavy bytecode magic. It's ok... M3L will eventually depend on Enigma. Completely restructured the mappings though. This way is better. =)
Diffstat (limited to 'src/cuchaz/enigma/bytecode/BytecodeIndexIterator.java')
-rw-r--r--src/cuchaz/enigma/bytecode/BytecodeIndexIterator.java180
1 files changed, 180 insertions, 0 deletions
diff --git a/src/cuchaz/enigma/bytecode/BytecodeIndexIterator.java b/src/cuchaz/enigma/bytecode/BytecodeIndexIterator.java
new file mode 100644
index 0000000..aadbeb2
--- /dev/null
+++ b/src/cuchaz/enigma/bytecode/BytecodeIndexIterator.java
@@ -0,0 +1,180 @@
1/*******************************************************************************
2 * Copyright (c) 2014 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Public License v3.0
5 * which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/gpl.html
7 *
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11package cuchaz.enigma.bytecode;
12
13import java.util.Iterator;
14
15import javassist.bytecode.BadBytecode;
16import javassist.bytecode.Bytecode;
17import javassist.bytecode.CodeAttribute;
18import javassist.bytecode.CodeIterator;
19import javassist.bytecode.Opcode;
20
21public class BytecodeIndexIterator implements Iterator<BytecodeIndexIterator.Index>
22{
23 public static class Index
24 {
25 private CodeIterator m_iter;
26 private int m_pos;
27 private boolean m_isWide;
28
29 protected Index( CodeIterator iter, int pos, boolean isWide )
30 {
31 m_iter = iter;
32 m_pos = pos;
33 m_isWide = isWide;
34 }
35
36 public int getIndex( )
37 {
38 if( m_isWide )
39 {
40 return m_iter.s16bitAt( m_pos );
41 }
42 else
43 {
44 return m_iter.byteAt( m_pos );
45 }
46 }
47
48 public void setIndex( int val )
49 throws BadBytecode
50 {
51 if( m_isWide )
52 {
53 m_iter.write16bit( val, m_pos );
54 }
55 else
56 {
57 if( val < 256 )
58 {
59 // we can write the byte
60 m_iter.writeByte( val, m_pos );
61 }
62 else
63 {
64 // we need to upgrade this instruction to LDC_W
65 assert( m_iter.byteAt( m_pos - 1 ) == Opcode.LDC );
66 m_iter.insertGap( m_pos - 1, 1 );
67 m_iter.writeByte( Opcode.LDC_W, m_pos - 1 );
68 m_iter.write16bit( val, m_pos );
69 m_isWide = true;
70
71 // move the iterator to the next opcode
72 m_iter.move( m_pos + 2 );
73 }
74 }
75
76 // sanity check
77 assert( val == getIndex() );
78 }
79
80 public boolean isValid( Bytecode bytecode )
81 {
82 return getIndex() >= 0 && getIndex() < bytecode.getConstPool().getSize();
83 }
84 }
85
86 private Bytecode m_bytecode;
87 private CodeAttribute m_attribute;
88 private CodeIterator m_iter;
89 private Index m_next;
90
91 public BytecodeIndexIterator( Bytecode bytecode )
92 throws BadBytecode
93 {
94 m_bytecode = bytecode;
95 m_attribute = bytecode.toCodeAttribute();
96 m_iter = m_attribute.iterator();
97
98 m_next = getNext();
99 }
100
101 @Override
102 public boolean hasNext( )
103 {
104 return m_next != null;
105 }
106
107 @Override
108 public Index next( )
109 {
110 Index out = m_next;
111 try
112 {
113 m_next = getNext();
114 }
115 catch( BadBytecode ex )
116 {
117 throw new Error( ex );
118 }
119 return out;
120 }
121
122 @Override
123 public void remove( )
124 {
125 throw new UnsupportedOperationException();
126 }
127
128 private Index getNext( )
129 throws BadBytecode
130 {
131 while( m_iter.hasNext() )
132 {
133 int pos = m_iter.next();
134 int opcode = m_iter.byteAt( pos );
135 switch( opcode )
136 {
137 // for only these opcodes, the next two bytes are a const pool reference
138 case Opcode.ANEWARRAY:
139 case Opcode.CHECKCAST:
140 case Opcode.INSTANCEOF:
141 case Opcode.INVOKEDYNAMIC:
142 case Opcode.INVOKEINTERFACE:
143 case Opcode.INVOKESPECIAL:
144 case Opcode.INVOKESTATIC:
145 case Opcode.INVOKEVIRTUAL:
146 case Opcode.LDC_W:
147 case Opcode.LDC2_W:
148 case Opcode.MULTIANEWARRAY:
149 case Opcode.NEW:
150 case Opcode.PUTFIELD:
151 case Opcode.PUTSTATIC:
152 case Opcode.GETFIELD:
153 case Opcode.GETSTATIC:
154 return new Index( m_iter, pos + 1, true );
155
156 case Opcode.LDC:
157 return new Index( m_iter, pos + 1, false );
158 }
159 }
160
161 return null;
162 }
163
164 public Iterable<Index> indices( )
165 {
166 return new Iterable<Index>( )
167 {
168 @Override
169 public Iterator<Index> iterator( )
170 {
171 return BytecodeIndexIterator.this;
172 }
173 };
174 }
175
176 public void saveChangesToBytecode( )
177 {
178 BytecodeTools.setBytecode( m_bytecode, m_attribute.getCode() );
179 }
180}