Author: britter Date: Wed Aug 30 19:34:23 2017 New Revision: 1806728 URL: http://svn.apache.org/viewvc?rev=1806728&view=rev Log: BCEL-276: LocalVariableTypeTable is not updated. Updated fix thanks to Mark Roberts. This closes #12 from GitHub.
Modified: commons/proper/bcel/trunk/src/changes/changes.xml commons/proper/bcel/trunk/src/main/java/org/apache/bcel/classfile/LocalVariable.java commons/proper/bcel/trunk/src/main/java/org/apache/bcel/generic/LocalVariableGen.java commons/proper/bcel/trunk/src/main/java/org/apache/bcel/generic/MethodGen.java Modified: commons/proper/bcel/trunk/src/changes/changes.xml URL: http://svn.apache.org/viewvc/commons/proper/bcel/trunk/src/changes/changes.xml?rev=1806728&r1=1806727&r2=1806728&view=diff ============================================================================== --- commons/proper/bcel/trunk/src/changes/changes.xml [utf-8] (original) +++ commons/proper/bcel/trunk/src/changes/changes.xml [utf-8] Wed Aug 30 19:34:23 2017 @@ -66,7 +66,7 @@ The <action> type attribute can be add,u <action issue="BCEL-287" type="fix" dev="britter" due-to="Mark Roberts">IINC does not handle -128 properly</action> <action issue="BCEL-283" type="fix" dev="britter" due-to="Mark Roberts">Support for StackMap should be different from StackMapTable</action> <action issue="BCEL-289" type="fix" dev="kinow">Crash when parsing constructor of inner classes with parameters annotated</action> - <action issue="BCEL-276" type="fix" dev="britter" due-to="Sam Yoon">LocalVariableTypeTable is not updated.</action> + <action issue="BCEL-276" type="fix" dev="britter" due-to="Sam Yoon, Mark Roberts">LocalVariableTypeTable is not updated.</action> <action issue="BCEL-277" type="fix" dev="britter" due-to="Sam Yoon">Resolving the String representation of a constant throws NoSuchElementException in case of CONSTANT_NameAndType constant.</action> </release> Modified: commons/proper/bcel/trunk/src/main/java/org/apache/bcel/classfile/LocalVariable.java URL: http://svn.apache.org/viewvc/commons/proper/bcel/trunk/src/main/java/org/apache/bcel/classfile/LocalVariable.java?rev=1806728&r1=1806727&r2=1806728&view=diff ============================================================================== --- commons/proper/bcel/trunk/src/main/java/org/apache/bcel/classfile/LocalVariable.java (original) +++ commons/proper/bcel/trunk/src/main/java/org/apache/bcel/classfile/LocalVariable.java Wed Aug 30 19:34:23 2017 @@ -41,6 +41,7 @@ public final class LocalVariable impleme * this method's frame. */ private ConstantPool constant_pool; + private int orig_index; // never changes; used to match up with LocalVariableTypeTable entries /** @@ -50,6 +51,7 @@ public final class LocalVariable impleme public LocalVariable(final LocalVariable c) { this(c.getStartPC(), c.getLength(), c.getNameIndex(), c.getSignatureIndex(), c.getIndex(), c.getConstantPool()); + this.orig_index = c.getOrigIndex(); } @@ -80,6 +82,28 @@ public final class LocalVariable impleme this.signature_index = signature_index; this.index = index; this.constant_pool = constant_pool; + this.orig_index = index; + } + + + /** + * @param start_pc Range in which the variable + * @param length ... is valid + * @param name_index Index in constant pool of variable name + * @param signature_index Index of variable's signature + * @param index Variable is `index'th local variable on the method's frame + * @param constant_pool Array of constants + * @param orig_index Variable is `index'th local variable on the method's frame prior to any changes + */ + public LocalVariable(final int start_pc, final int length, final int name_index, final int signature_index, final int index, + final ConstantPool constant_pool, final int orig_index) { + this.start_pc = start_pc; + this.length = length; + this.name_index = name_index; + this.signature_index = signature_index; + this.index = index; + this.constant_pool = constant_pool; + this.orig_index = orig_index; } @@ -171,6 +195,14 @@ public final class LocalVariable impleme } + /** + * @return index of register where variable was originally stored + */ + public final int getOrigIndex() { + return orig_index; + } + + /** * @return Start of range where he variable is valid */ Modified: commons/proper/bcel/trunk/src/main/java/org/apache/bcel/generic/LocalVariableGen.java URL: http://svn.apache.org/viewvc/commons/proper/bcel/trunk/src/main/java/org/apache/bcel/generic/LocalVariableGen.java?rev=1806728&r1=1806727&r2=1806728&view=diff ============================================================================== --- commons/proper/bcel/trunk/src/main/java/org/apache/bcel/generic/LocalVariableGen.java (original) +++ commons/proper/bcel/trunk/src/main/java/org/apache/bcel/generic/LocalVariableGen.java Wed Aug 30 19:34:23 2017 @@ -37,6 +37,7 @@ public class LocalVariableGen implements private Type type; private InstructionHandle start; private InstructionHandle end; + private int orig_index; // never changes; used to match up with LocalVariableTypeTable entries /** @@ -59,6 +60,25 @@ public class LocalVariableGen implements this.index = index; setStart(start); setEnd(end); + this.orig_index = index; + } + + + /** + * Generate a local variable that with index `index'. Note that double and long + * variables need two indexs. Index indices have to be provided by the user. + * + * @param index index of local variable + * @param name its name + * @param type its type + * @param start from where the instruction is valid (null means from the start) + * @param end until where the instruction is valid (null means to the end) + * @param orig_index index of local variable prior to any changes to index + */ + public LocalVariableGen(final int index, final String name, final Type type, final InstructionHandle start, + final InstructionHandle end, final int orig_index) { + this(index, name, type, start, end); + this.orig_index = orig_index; } @@ -89,7 +109,7 @@ public class LocalVariableGen implements final int name_index = cp.addUtf8(name); final int signature_index = cp.addUtf8(type.getSignature()); return new LocalVariable(start_pc, length, name_index, signature_index, index, cp - .getConstantPool()); + .getConstantPool(), orig_index); } @@ -103,6 +123,11 @@ public class LocalVariableGen implements } + public int getOrigIndex() { + return orig_index; + } + + @Override public void setName( final String name ) { this.name = name; Modified: commons/proper/bcel/trunk/src/main/java/org/apache/bcel/generic/MethodGen.java URL: http://svn.apache.org/viewvc/commons/proper/bcel/trunk/src/main/java/org/apache/bcel/generic/MethodGen.java?rev=1806728&r1=1806727&r2=1806728&view=diff ============================================================================== --- commons/proper/bcel/trunk/src/main/java/org/apache/bcel/generic/MethodGen.java (original) +++ commons/proper/bcel/trunk/src/main/java/org/apache/bcel/generic/MethodGen.java Wed Aug 30 19:34:23 2017 @@ -66,7 +66,6 @@ public class MethodGen extends FieldGenO private int max_stack; private InstructionList il; private boolean strip_attributes; - private LocalVariableTable local_variable_table = null; private LocalVariableTypeTable local_variable_type_table = null; private final List<LocalVariableGen> variable_vec = new ArrayList<>(); private final List<LineNumberGen> line_number_vec = new ArrayList<>(); @@ -225,10 +224,9 @@ public class MethodGen extends FieldGenO } } } else if (a instanceof LocalVariableTable) { - this.local_variable_table = (LocalVariableTable) a; - updateLocalVariableTable(this.local_variable_table); + updateLocalVariableTable((LocalVariableTable) a); } else if (a instanceof LocalVariableTypeTable) { - this.local_variable_type_table = (LocalVariableTypeTable) a; + this.local_variable_type_table = (LocalVariableTypeTable) a.copy(cp.getConstantPool()); } else { addCodeAttribute(a); } @@ -259,18 +257,19 @@ public class MethodGen extends FieldGenO * index is slot+2 * @param start from where the variable is valid * @param end until where the variable is valid + * @param orig_index the index of the local variable prior to any modifications * @return new local variable object * @see LocalVariable */ public LocalVariableGen addLocalVariable( final String name, final Type type, final int slot, - final InstructionHandle start, final InstructionHandle end ) { + final InstructionHandle start, final InstructionHandle end, final int orig_index ) { final byte t = type.getType(); if (t != Const.T_ADDRESS) { final int add = type.getSize(); if (slot + add > max_locals) { max_locals = slot + add; } - final LocalVariableGen l = new LocalVariableGen(slot, name, type, start, end); + final LocalVariableGen l = new LocalVariableGen(slot, name, type, start, end, orig_index); int i; if ((i = variable_vec.indexOf(l)) >= 0) { variable_vec.set(i, l); @@ -283,6 +282,24 @@ public class MethodGen extends FieldGenO + " as type for local variable"); } + + /** + * Adds a local variable to this method. + * + * @param name variable name + * @param type variable type + * @param slot the index of the local variable, if type is long or double, the next available + * index is slot+2 + * @param start from where the variable is valid + * @param end until where the variable is valid + * @return new local variable object + * @see LocalVariable + */ + public LocalVariableGen addLocalVariable( final String name, final Type type, final int slot, + final InstructionHandle start, final InstructionHandle end ) { + return addLocalVariable(name, type, slot, start, end, slot); + } + /** * Adds a local variable to this method and assigns an index automatically. * @@ -366,6 +383,12 @@ public class MethodGen extends FieldGenO .getConstantPool()); } + /** + * @return `LocalVariableTypeTable' attribute of this method. + */ + public LocalVariableTypeTable getLocalVariableTypeTable() { + return local_variable_type_table; + } /** * Give an instruction a line number corresponding to the source code line. @@ -547,6 +570,13 @@ public class MethodGen extends FieldGenO /** + * Remove the LocalVariableTypeTable + */ + public void removeLocalVariableTypeTable( ) { + local_variable_type_table = null; + } + + /** * Remove a code attribute. */ public void removeCodeAttribute( final Attribute a ) { @@ -558,6 +588,7 @@ public class MethodGen extends FieldGenO * Remove all code attributes. */ public void removeCodeAttributes() { + local_variable_type_table = null; code_attrs_vec.clear(); } @@ -619,15 +650,13 @@ public class MethodGen extends FieldGenO /* Create LocalVariableTable and LineNumberTable attributes (for debuggers, e.g.) */ if ((variable_vec.size() > 0) && !strip_attributes) { - if (local_variable_table != null) { - updateLocalVariableTable(local_variable_table); - } + updateLocalVariableTable(getLocalVariableTable(_cp)); addCodeAttribute(lvt = getLocalVariableTable(_cp)); } if (local_variable_type_table != null) { // LocalVariable length in LocalVariableTypeTable is not updated automatically. It's a difference with LocalVariableTable. if (lvt != null) { - adjustLocalVariableLength(lvt); + adjustLocalVariableTypeTable(lvt); } addCodeAttribute(local_variable_type_table); } @@ -671,6 +700,9 @@ public class MethodGen extends FieldGenO if (lvt != null) { removeCodeAttribute(lvt); } + if (local_variable_type_table != null) { + removeCodeAttribute(local_variable_type_table); + } if (lnt != null) { removeCodeAttribute(lnt); } @@ -696,19 +728,23 @@ public class MethodGen extends FieldGenO if (null == end) { end = il.getEnd(); } + // Since we are recreating the LocalVaraible, we must + // propagate the orig_index to new copy. addLocalVariable(l.getName(), Type.getType(l.getSignature()), l - .getIndex(), start, end); + .getIndex(), start, end, l.getOrigIndex()); } } - private void adjustLocalVariableLength(final LocalVariableTable lvt) { + private void adjustLocalVariableTypeTable(final LocalVariableTable lvt) { final LocalVariable[] lv = lvt.getLocalVariableTable(); final LocalVariable[] lvg = local_variable_type_table.getLocalVariableTypeTable(); for (final LocalVariable element : lvg) { for (final LocalVariable l : lv) { - if (element.getName().equals(l.getName()) && element.getIndex() == l.getIndex()) { + if (element.getName().equals(l.getName()) && element.getIndex() == l.getOrigIndex()) { element.setLength(l.getLength()); + element.setStartPC(l.getStartPC()); + element.setIndex(l.getIndex()); break; } }