111 lines
4.2 KiB
Java
111 lines
4.2 KiB
Java
/*******************************************************************************
|
|
* Copyright (c) 2002,2006 IBM Corporation.
|
|
* All rights reserved. This program and the accompanying materials
|
|
* are made available under the terms of the Eclipse Public License v1.0
|
|
* which accompanies this distribution, and is available at
|
|
* http://www.eclipse.org/legal/epl-v10.html
|
|
*
|
|
* Contributors:
|
|
* IBM Corporation - initial API and implementation
|
|
*******************************************************************************/
|
|
package com.ibm.wala.shrikeCT;
|
|
|
|
/**
|
|
* This class reads LocalVariableTable attributes.
|
|
*
|
|
* Instead of constructing a LocalVariableTable directly, consider just calling LocalVariableTable.makeVarMap for convenient access
|
|
* to aggregate local variable data from all the LocalVariableTable attributes for a given Code.
|
|
*/
|
|
public final class LocalVariableTableReader extends AttributeReader {
|
|
public LocalVariableTableReader(ClassReader.AttrIterator iter) throws InvalidClassFileException {
|
|
super(iter, "LocalVariableTable");
|
|
|
|
int offset = attr + 6;
|
|
checkSize(offset, 2);
|
|
int count = cr.getUShort(offset);
|
|
offset += 2;
|
|
checkSize(offset, count * 10);
|
|
}
|
|
|
|
/**
|
|
* @return the raw line number table data, a flattened sequence of (startPC, PClength, nameIndex, typeIndex, var) tuples
|
|
*/
|
|
public int[] getRawTable() {
|
|
int count = cr.getUShort(attr + 6);
|
|
int[] r = new int[count * 5];
|
|
int offset = attr + 8;
|
|
for (int i = 0; i < r.length; i++) {
|
|
r[i] = cr.getUShort(offset);
|
|
offset += 2;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
private static int[] makeVarVector(int[] curVector, int varIndex, int nameIndex, int typeIndex) {
|
|
int[] newVector;
|
|
if (curVector == null) {
|
|
newVector = new int[(varIndex + 1) * 2];
|
|
} else {
|
|
newVector = new int[Math.max(curVector.length, (varIndex + 1) * 2)];
|
|
System.arraycopy(curVector, 0, newVector, 0, curVector.length);
|
|
}
|
|
newVector[varIndex * 2] = nameIndex;
|
|
newVector[varIndex * 2 + 1] = typeIndex;
|
|
return newVector;
|
|
}
|
|
|
|
/**
|
|
* @return an array mapping bytecode offsets to arrays representing the local variable maps for each offset; a local variable map
|
|
* is represented as an array of localVars*2 elements, containing a pair (nameIndex, typeIndex) for each local variable; a
|
|
* pair (0,0) indicates there is no information for that local variable at that offset
|
|
*/
|
|
public static int[][] makeVarMap(CodeReader code) throws InvalidClassFileException, IllegalArgumentException {
|
|
if (code == null) {
|
|
throw new IllegalArgumentException();
|
|
}
|
|
|
|
int[][] r = null;
|
|
ClassReader cr = code.getClassReader();
|
|
|
|
ClassReader.AttrIterator iter = new ClassReader.AttrIterator();
|
|
code.initAttributeIterator(iter);
|
|
for (; iter.isValid(); iter.advance()) {
|
|
if (iter.getName().equals("LocalVariableTable")) {
|
|
if (r == null) {
|
|
r = new int[code.getBytecodeLength()][];
|
|
}
|
|
|
|
// check length
|
|
new LocalVariableTableReader(iter);
|
|
int attr = iter.getRawOffset();
|
|
int count = cr.getUShort(attr + 6);
|
|
int offset = attr + 8;
|
|
for (int j = 0; j < count; j++) {
|
|
int startPC = cr.getUShort(offset);
|
|
int length = cr.getUShort(offset + 2);
|
|
int nameIndex = cr.getUShort(offset + 4);
|
|
int typeIndex = cr.getUShort(offset + 6);
|
|
int varIndex = cr.getUShort(offset + 8);
|
|
offset += 10;
|
|
|
|
if (varIndex < 0) {
|
|
throw new InvalidClassFileException(offset, "Invalid variable index " + varIndex + " in LocalVariableTable");
|
|
} else if (startPC < 0) {
|
|
throw new InvalidClassFileException(offset, "Invalid startPC " + startPC + " in LocalVariableTable");
|
|
} else if (startPC + length > r.length) {
|
|
throw new InvalidClassFileException(offset, "Invalid startPC+length " + (startPC + length) + " > " + r.length
|
|
+ " in LocalVariableTable");
|
|
}
|
|
|
|
for (int k = startPC; k < startPC + length; k++) {
|
|
int[] newVector = makeVarVector(r[k], varIndex, nameIndex, typeIndex);
|
|
r[k] = newVector;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return r;
|
|
}
|
|
}
|