8064516: BCEL still corrupts generic methods if bytecode offsets are modified
Added comprehensive support for LocalVariableTypeTable to MethodGen. Reviewed-by: joehw
This commit is contained in:
parent
23a78f8c2f
commit
a02a2a54b6
@ -213,6 +213,10 @@ public class DescendingVisitor implements Visitor {
|
||||
public void visitLocalVariableTypeTable(LocalVariableTypeTable obj) {
|
||||
stack.push(obj);
|
||||
obj.accept(visitor);
|
||||
|
||||
LocalVariable[] vars = obj.getLocalVariableTypeTable();
|
||||
for(int i=0; i < vars.length; i++)
|
||||
vars[i].accept(this);
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
|
@ -87,6 +87,7 @@ public class MethodGen extends FieldGenOrMethodGen {
|
||||
private boolean strip_attributes;
|
||||
|
||||
private ArrayList variable_vec = new ArrayList();
|
||||
private ArrayList type_vec = new ArrayList();
|
||||
private ArrayList line_number_vec = new ArrayList();
|
||||
private ArrayList exception_vec = new ArrayList();
|
||||
private ArrayList throws_vec = new ArrayList();
|
||||
@ -259,11 +260,10 @@ public class MethodGen extends FieldGenOrMethodGen {
|
||||
l.getIndex(), start, end);
|
||||
}
|
||||
} else if (a instanceof LocalVariableTypeTable) {
|
||||
LocalVariable[] oldLV = ((LocalVariableTypeTable) a).getLocalVariableTypeTable();
|
||||
int lvLength = oldLV.length;
|
||||
LocalVariable[] newLV = new LocalVariable[lvLength];
|
||||
for (int k = 0; k < lvLength; k++) {
|
||||
LocalVariable l = oldLV[k];
|
||||
LocalVariable[] lv = ((LocalVariableTypeTable) a).getLocalVariableTypeTable();
|
||||
removeLocalVariableTypes();
|
||||
for (int k = 0; k < lv.length; k++) {
|
||||
LocalVariable l = lv[k];
|
||||
InstructionHandle start = il.findHandle(l.getStartPC());
|
||||
InstructionHandle end = il.findHandle(l.getStartPC() + l.getLength());
|
||||
// Repair malformed handles
|
||||
@ -273,16 +273,9 @@ public class MethodGen extends FieldGenOrMethodGen {
|
||||
if (null == end) {
|
||||
end = il.getEnd();
|
||||
}
|
||||
LocalVariable newVar = new LocalVariable(l);
|
||||
int startPosition = start.getPosition();
|
||||
newVar.setStartPC(startPosition);
|
||||
newVar.setLength(end.getPosition() - startPosition);
|
||||
newLV[k] = newVar;
|
||||
addLocalVariableType(l.getName(), Type.getType(l.getSignature()), l
|
||||
.getIndex(), start, end);
|
||||
}
|
||||
LocalVariableTypeTable newLVTT = new LocalVariableTypeTable(
|
||||
(LocalVariableTypeTable)a);
|
||||
newLVTT.setLocalVariableTable(newLV);
|
||||
addCodeAttribute(newLVTT);
|
||||
} else
|
||||
addCodeAttribute(a);
|
||||
}
|
||||
@ -414,6 +407,31 @@ public class MethodGen extends FieldGenOrMethodGen {
|
||||
return lg;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the range of the variable has not been set yet, it will be set to be
|
||||
* val id from the start to the end of the instruction list.
|
||||
*
|
||||
* @return array of declared local variable types sorted by index
|
||||
*/
|
||||
private LocalVariableGen[] getLocalVariableTypes() {
|
||||
int size = type_vec.size();
|
||||
LocalVariableGen[] lg = new LocalVariableGen[size];
|
||||
type_vec.toArray(lg);
|
||||
|
||||
for(int i=0; i < size; i++) {
|
||||
if(lg[i].getStart() == null)
|
||||
lg[i].setStart(il.getStart());
|
||||
|
||||
if(lg[i].getEnd() == null)
|
||||
lg[i].setEnd(il.getEnd());
|
||||
}
|
||||
|
||||
if(size > 1)
|
||||
sort(lg, 0, size - 1);
|
||||
|
||||
return lg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return `LocalVariableTable' attribute of all the local variables of this method.
|
||||
*/
|
||||
@ -429,6 +447,68 @@ public class MethodGen extends FieldGenOrMethodGen {
|
||||
2 + lv.length * 10, lv, cp.getConstantPool());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return `LocalVariableTypeTable' attribute of all the local variable
|
||||
* types of this method.
|
||||
*/
|
||||
public LocalVariableTypeTable getLocalVariableTypeTable(ConstantPoolGen cp) {
|
||||
LocalVariableGen[] lg = getLocalVariableTypes();
|
||||
int size = lg.length;
|
||||
LocalVariable[] lv = new LocalVariable[size];
|
||||
|
||||
for(int i=0; i < size; i++)
|
||||
lv[i] = lg[i].getLocalVariable(cp);
|
||||
|
||||
return new LocalVariableTypeTable(cp.addUtf8("LocalVariableTypeTable"),
|
||||
2 + lv.length * 10, lv, cp.getConstantPool());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a local variable type 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
|
||||
*/
|
||||
private LocalVariableGen addLocalVariableType(String name, Type type, int slot,
|
||||
InstructionHandle start,
|
||||
InstructionHandle end) {
|
||||
byte t = type.getType();
|
||||
|
||||
if(t != Constants.T_ADDRESS) {
|
||||
int add = type.getSize();
|
||||
|
||||
if(slot + add > max_locals)
|
||||
max_locals = slot + add;
|
||||
|
||||
LocalVariableGen l = new LocalVariableGen(slot, name, type, start, end);
|
||||
int i;
|
||||
|
||||
if((i = type_vec.indexOf(l)) >= 0) // Overwrite if necessary
|
||||
type_vec.set(i, l);
|
||||
else
|
||||
type_vec.add(l);
|
||||
|
||||
return l;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Can not use " + type +
|
||||
" as type for local variable");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all local variable types.
|
||||
*/
|
||||
private void removeLocalVariableTypes() {
|
||||
type_vec.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Give an instruction a line number corresponding to the source code line.
|
||||
*
|
||||
@ -645,12 +725,17 @@ public class MethodGen extends FieldGenOrMethodGen {
|
||||
|
||||
LineNumberTable lnt = null;
|
||||
LocalVariableTable lvt = null;
|
||||
LocalVariableTypeTable lvtt = null;
|
||||
|
||||
/* Create LocalVariableTable and LineNumberTable attributes (for debuggers, e.g.)
|
||||
/* Create LocalVariableTable, LocalvariableTypeTable, and LineNumberTable
|
||||
* attributes (for debuggers, e.g.)
|
||||
*/
|
||||
if((variable_vec.size() > 0) && !strip_attributes)
|
||||
addCodeAttribute(lvt = getLocalVariableTable(cp));
|
||||
|
||||
if((type_vec.size() > 0) && !strip_attributes)
|
||||
addCodeAttribute(lvtt = getLocalVariableTypeTable(cp));
|
||||
|
||||
if((line_number_vec.size() > 0) && !strip_attributes)
|
||||
addCodeAttribute(lnt = getLineNumberTable(cp));
|
||||
|
||||
@ -699,6 +784,7 @@ public class MethodGen extends FieldGenOrMethodGen {
|
||||
|
||||
// Undo effects of adding attributes
|
||||
if(lvt != null) removeCodeAttribute(lvt);
|
||||
if(lvtt != null) removeCodeAttribute(lvtt);
|
||||
if(lnt != null) removeCodeAttribute(lnt);
|
||||
if(code != null) removeAttribute(code);
|
||||
if(et != null) removeAttribute(et);
|
||||
|
Loading…
Reference in New Issue
Block a user