diff options
| author | 2014-07-27 22:33:21 -0400 | |
|---|---|---|
| committer | 2014-07-27 22:33:21 -0400 | |
| commit | d7321b5b0d38c575e54c770f7aa18dacbacab3c8 (patch) | |
| tree | ef4b3e0f83b1fe89125c2674fec023871e70c0d8 /src/cuchaz/enigma/bytecode/BytecodeIndexIterator.java | |
| parent | made gui responsive to caret position and show identifier info (diff) | |
| download | enigma-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.java | 180 |
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 | ******************************************************************************/ | ||
| 11 | package cuchaz.enigma.bytecode; | ||
| 12 | |||
| 13 | import java.util.Iterator; | ||
| 14 | |||
| 15 | import javassist.bytecode.BadBytecode; | ||
| 16 | import javassist.bytecode.Bytecode; | ||
| 17 | import javassist.bytecode.CodeAttribute; | ||
| 18 | import javassist.bytecode.CodeIterator; | ||
| 19 | import javassist.bytecode.Opcode; | ||
| 20 | |||
| 21 | public 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 | } | ||