WALA/com.ibm.wala.shrike/src/com/ibm/wala/shrikeCT/StackMapConstants.java

239 lines
5.5 KiB
Java

package com.ibm.wala.shrikeCT;
import static com.ibm.wala.shrikeCT.StackMapTableWriter.writeUByte;
import static com.ibm.wala.shrikeCT.StackMapTableWriter.writeUShort;
import java.io.IOException;
import java.io.OutputStream;
import com.ibm.wala.shrikeBT.analysis.Analyzer;
public class StackMapConstants {
interface StackMapType {
void write(OutputStream s, ClassWriter writer) throws IOException;
int size();
boolean isObject();
}
public enum Item implements StackMapType {
ITEM_Top(0),
ITEM_Integer(1),
ITEM_Float(2),
ITEM_Double(3) {
@Override
public int size() {
return 2;
}
},
ITEM_Long(4) {
@Override
public int size() {
return 2;
}
},
ITEM_Null(5),
ITEM_UninitializedThis(6),
ITEM_Object(7) {
@Override
public boolean isObject() {
return true;
}
},
ITEM_Uninitalized(8) {
@Override
public boolean isObject() {
return true;
}
};
private final byte code;
Item(int code) {
this.code = (byte)code;
}
@Override
public boolean isObject() {
return false;
}
@Override
public int size() {
return 1;
}
@Override
public void write(OutputStream s, ClassWriter writer) throws IOException {
writeUByte(s, code);
}
}
public static class UninitializedType implements StackMapType {
private final String type;
private final int offset;
public UninitializedType(String type) {
assert type.startsWith("#");
this.type = Analyzer.stripSharp(type);
this.offset = Integer.parseInt(type.substring(1, type.lastIndexOf('#')));
}
@Override
public void write(OutputStream s, ClassWriter writer) throws IOException {
Item.ITEM_Uninitalized.write(s, writer);
writeUShort(s, offset);
}
@Override
public int size() {
return Item.ITEM_Uninitalized.size();
}
@Override
public boolean isObject() {
return true;
}
@Override
public String toString() {
return "uninit:" + type;
}
}
public static class ObjectType implements StackMapType {
private final String type;
ObjectType(ClassReader cr, int typeIndex) throws IllegalArgumentException, InvalidClassFileException {
this(cr.getCP().getCPString(typeIndex));
}
ObjectType(String type) {
this.type = type;
}
@Override
public int size() {
return Item.ITEM_Object.size();
}
@Override
public boolean isObject() {
return true;
}
@Override
public String toString() {
return "obj:" + type;
}
@Override
public void write(OutputStream s, ClassWriter writer) throws IOException {
Item.ITEM_Object.write(s, writer);
if ("L;".equals(type)) {
writeUShort(s, writer.addCPClass("java/lang/Object"));
} else if (type.startsWith("L")) {
writeUShort(s, writer.addCPClass(type.substring(1, type.length()-1)));
} else {
writeUShort(s, writer.addCPClass(type));
}
}
}
public static Item items[] = {
Item.ITEM_Top,
Item.ITEM_Integer,
Item.ITEM_Float,
Item.ITEM_Double,
Item.ITEM_Long,
Item.ITEM_Null,
Item.ITEM_UninitializedThis,
Item.ITEM_Object,
Item.ITEM_Uninitalized
};
public static class StackMapFrame {
public StackMapFrame(StackMapFrame frame, int newOffset) {
this(frame.frameType, newOffset, frame.localTypes, frame.stackTypes);
}
public StackMapFrame(int frameType, int offset, StackMapType[] localTypes, StackMapType[] stackTypes) {
this.frameType = frameType;
this.offset = offset;
this.localTypes = localTypes;
this.stackTypes = stackTypes;
}
private final int frameType;
private final int offset;
private final StackMapType[] localTypes;
private final StackMapType[] stackTypes;
public int getFrameType() {
return frameType;
}
public int getOffset() {
return offset;
}
public StackMapType[] getLocalTypes() {
return localTypes;
}
public StackMapType[] getStackTypes() {
return stackTypes;
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("frame type: ").append(frameType).append("\n");
sb.append(" offset: ").append(offset).append("\n");
sb.append(" locals\n");
for(int i = 0; i < localTypes.length; i++) {
sb.append(" ").append(localTypes[i]).append("\n");
}
sb.append(" stack\n");
for(int i = 0; i < stackTypes.length; i++) {
sb.append(" ").append(stackTypes[i]).append("\n");
}
return sb.toString();
}
public void write(OutputStream out, ClassWriter writer) throws IOException {
// frame type
writeUByte(out, frameType);
// offset delta
writeUShort(out, offset);
// locals
if (localTypes != null) {
writeUShort(out, localTypes.length);
for(StackMapType type : localTypes) {
type.write(out, writer);
}
} else {
writeUShort(out, 0);
}
// stack
if (stackTypes != null) {
writeUShort(out, stackTypes.length);
for(int j = stackTypes.length; j > 0; ) {
stackTypes[--j].write(out, writer);
}
} else {
writeUShort(out, 0);
}
}
}
}