package soot.JastAddJ;
import java.util.HashSet;import java.util.LinkedHashSet;import java.io.File;import java.util.*;import beaver.*;import java.util.ArrayList;import java.util.zip.*;import java.io.*;import java.io.FileNotFoundException;import java.util.Collection;import soot.*;import soot.util.*;import soot.jimple.*;import soot.coffi.ClassFile;import soot.coffi.method_info;import soot.coffi.CONSTANT_Utf8_info;import soot.tagkit.SourceFileTag;import soot.coffi.CoffiMethodSource;
public class BytecodeParser extends java.lang.Object implements Flags, BytecodeReader {
// Declared in BytecodeReader.jrag at line 13
public CompilationUnit read(InputStream is, String fullName, Program p) throws FileNotFoundException, IOException {
return new BytecodeParser(is, fullName).parse(null, null, p);
}
// Declared in BytecodeReader.jrag at line 17
public static final boolean VERBOSE = false;
// Declared in BytecodeReader.jrag at line 19
private DataInputStream is;
// Declared in BytecodeReader.jrag at line 20
public CONSTANT_Class_Info classInfo;
// Declared in BytecodeReader.jrag at line 21
public String outerClassName;
// Declared in BytecodeReader.jrag at line 22
public String name;
// Declared in BytecodeReader.jrag at line 24
public BytecodeParser(byte[] buffer, int size, String name) {
//this.is = new DataInputStream(new DummyInputStream(buffer, size));
this.is = new DataInputStream(new ByteArrayInputStream(buffer, 0, size));
this.name = name;
}
// Declared in BytecodeReader.jrag at line 29
public BytecodeParser(InputStream in, String name) {
//this.is = new DataInputStream(new DummyInputStream(buffer, size));
this.is = new DataInputStream(new DummyInputStream(in));
this.name = name;
}
// Declared in BytecodeReader.jrag at line 35
public BytecodeParser() {
this("");
}
// Declared in BytecodeReader.jrag at line 38
public BytecodeParser(String name) {
if (!name.endsWith(".class")) {
//name = name.replaceAll("\\.", "/") + ".class";
name = name.replace('.', '/') + ".class";
}
this.name = name;
}
// Declared in BytecodeReader.jrag at line 46
private static class DummyInputStream extends InputStream {
byte[] bytes;
int pos;
int size;
public DummyInputStream(byte[] buffer, int size) {
bytes = buffer;
this.size = size;
}
public DummyInputStream(InputStream is) {
bytes = new byte[1024];
int index = 0;
size = 1024;
try {
int status;
do {
status = is.read(bytes, index, size - index);
if(status != -1) {
index += status;
if(index == size) {
byte[] newBytes = new byte[size*2];
System.arraycopy(bytes, 0, newBytes, 0, size);
bytes = newBytes;
size *= 2;
}
}
} while (status != -1);
} catch (IOException e) {
System.err.println("Something went wrong trying to read " + is);
//System.exit(1);
}
size = index;
pos = 0;
}
public int available() {
return size - pos;
}
public void close() {
}
public void mark(int readlimit) {
}
public boolean markSupported() {
return false;
}
public int read(byte[] b) {
int actualLength = Math.min(b.length, size-pos);
System.arraycopy(bytes, pos, b, 0, actualLength);
pos += actualLength;
return actualLength;
}
public int read(byte[] b, int offset, int length) {
int actualLength = Math.min(length, size-pos);
System.arraycopy(bytes, pos, b, offset, actualLength);
pos += actualLength;
return actualLength;
}
public void reset() {
}
public long skip(long n) {
if(size == pos)
return -1;
long skipSize = Math.min(n, size-pos);
pos += skipSize;
return skipSize;
}
public int read() throws IOException {
if(pos < size) {
int i = bytes[pos++];
if(i < 0)
i = 256 + i;
return i;
}
return -1;
}
}
// Declared in BytecodeReader.jrag at line 130
public int next() {
try {
return is.read();
} catch (IOException e) {
System.exit(1);
}
return -1;
}
// Declared in BytecodeReader.jrag at line 139
public int u1() {
try {
return is.readUnsignedByte();
} catch (IOException e) {
System.exit(1);
}
return -1;
}
// Declared in BytecodeReader.jrag at line 148
public int u2() {
try {
return is.readUnsignedShort();
} catch (IOException e) {
System.exit(1);
}
return -1;
}
// Declared in BytecodeReader.jrag at line 157
public int u4() {
try {
return is.readInt();
} catch (IOException e) {
System.exit(1);
}
return -1;
}
// Declared in BytecodeReader.jrag at line 166
public int readInt() {
try {
return is.readInt();
} catch (IOException e) {
System.exit(1);
}
return -1;
}
// Declared in BytecodeReader.jrag at line 175
public float readFloat() {
try {
return is.readFloat();
} catch (IOException e) {
System.exit(1);
}
return -1;
}
// Declared in BytecodeReader.jrag at line 184
public long readLong() {
try {
return is.readLong();
} catch (IOException e) {
System.exit(1);
}
return -1;
}
// Declared in BytecodeReader.jrag at line 193
public double readDouble() {
try {
return is.readDouble();
} catch (IOException e) {
System.exit(1);
}
return -1;
}
// Declared in BytecodeReader.jrag at line 202
public String readUTF() {
try {
return is.readUTF();
} catch (IOException e) {
System.exit(1);
}
return "";
}
// Declared in BytecodeReader.jrag at line 211
public void skip(int length) {
try {
is.skip(length);
} catch (IOException e) {
System.exit(1);
}
}
// Declared in BytecodeReader.jrag at line 219
public void error(String s) {
throw new RuntimeException(s);
}
// Declared in BytecodeReader.jrag at line 223
public void print(String s) {
//System.out.print(s);
}
// Declared in BytecodeReader.jrag at line 227
public void println(String s) {
print(s + "\n");
}
// Declared in BytecodeReader.jrag at line 231
public void println() {
print("\n");
}
// Declared in BytecodeReader.jrag at line 235
public CompilationUnit parse(TypeDecl outerTypeDecl, String outerClassName, Program classPath, boolean isInner)
throws FileNotFoundException, IOException {
isInnerClass = isInner;
return parse(outerTypeDecl, outerClassName, classPath);
}
// Declared in BytecodeReader.jrag at line 241
public CompilationUnit parse(TypeDecl outerTypeDecl, String outerClassName, Program classPath)
throws FileNotFoundException, IOException {
//InputStream file = ClassLoader.getSystemResourceAsStream(name);
if(is == null) {
FileInputStream file = new FileInputStream(name);
//System.err.println("/home/torbjorn/sandbox/jdk/" + name);
if(file == null) {
throw new FileNotFoundException(name);
}
// // Does not work without DummyInputStream. Why?
//is = new DataInputStream(new DummyInputStream(new BufferedInputStream(file)));
is = new DataInputStream(new BufferedInputStream(file));
}
if(BytecodeParser.VERBOSE)
println("Parsing byte codes in " + name);
this.outerClassName = outerClassName;
parseMagic();
parseMinor();
parseMajor();
parseConstantPool();
CompilationUnit cu = new CompilationUnit();
TypeDecl typeDecl = parseTypeDecl();
cu.setPackageDecl(classInfo.packageDecl());
cu.addTypeDecl(typeDecl);
parseFields(typeDecl);
parseMethods(typeDecl);
new Attributes.TypeAttributes(this, typeDecl, outerTypeDecl, classPath);
is.close();
is = null;
return cu;
}
// Declared in BytecodeReader.jrag at line 278
public void parseMagic() {
if (next() != 0xca || next() != 0xfe || next() != 0xba || next() != 0xbe)
error("magic error");
}
// Declared in BytecodeReader.jrag at line 283
public void parseMinor() {
int low = u1();
int high = u1();
if(BytecodeParser.VERBOSE)
println("Minor: " + high + "." + low);
}
// Declared in BytecodeReader.jrag at line 290
public void parseMajor() {
int low = u1();
int high = u1();
if(BytecodeParser.VERBOSE)
println("Major: " + high + "." + low);
}
// Declared in BytecodeReader.jrag at line 297
public boolean isInnerClass = false;
// Declared in BytecodeReader.jrag at line 299
public TypeDecl parseTypeDecl() {
int flags = u2();
Modifiers modifiers = modifiers(flags & 0xfddf);
if((flags & (ACC_INTERFACE | ACC_ENUM)) == ACC_ENUM) {
// Modifiers <ID:String> /[SuperClassAccess:Access]/ Implements:Access* BodyDecl*;
EnumDecl decl = new EnumDecl();
decl.setModifiers(modifiers);
decl.setID(parseThisClass());
Access superClass = parseSuperClass();
decl.setImplementsList(parseInterfaces(new List()));
return decl;
}
else if ((flags & ACC_INTERFACE) == 0) {
ClassDecl decl = new ClassDecl();
decl.setModifiers(modifiers);
decl.setID(parseThisClass());
Access superClass = parseSuperClass();
decl.setSuperClassAccessOpt(superClass == null ? new Opt()
: new Opt(superClass));
decl.setImplementsList(parseInterfaces(new List()));
return decl;
} else if((flags & ACC_ANNOTATION) == 0) {
InterfaceDecl decl = new InterfaceDecl();
decl.setModifiers(modifiers);
decl.setID(parseThisClass());
Access superClass = parseSuperClass();
decl.setSuperInterfaceIdList(
parseInterfaces(
superClass == null ? new List()
: new List().add(superClass)));
return decl;
} else {
AnnotationDecl decl = new AnnotationDecl();
decl.setModifiers(modifiers);
decl.setID(parseThisClass());
Access superClass = parseSuperClass();
parseInterfaces(
superClass == null ? new List()
: new List().add(superClass));
return decl;
}
}
// Declared in BytecodeReader.jrag at line 343
public String parseThisClass() {
int index = u2();
CONSTANT_Class_Info info = (CONSTANT_Class_Info) constantPool[index];
classInfo = info;
return info.simpleName();
}
// Declared in BytecodeReader.jrag at line 350
public Access parseSuperClass() {
int index = u2();
if (index == 0)
return null;
CONSTANT_Class_Info info = (CONSTANT_Class_Info) constantPool[index];
return info.access();
}
// Declared in BytecodeReader.jrag at line 358
public List parseInterfaces(List list) {
int count = u2();
for (int i = 0; i < count; i++) {
CONSTANT_Class_Info info = (CONSTANT_Class_Info) constantPool[u2()];
list.add(info.access());
}
return list;
}
// Declared in BytecodeReader.jrag at line 368
public Access fromClassName(String s) {
// Sample ClassName: a/b/c$d$e
// the package name ends at the last '/'
// after that follows a list of type names separated by '$'
// all except the first are nested types
String packageName = "";
int index = s.lastIndexOf('/');
if(index != -1)
packageName = s.substring(0, index).replace('/', '.');
String typeName = s.substring(index + 1, s.length());
if(typeName.indexOf('$') != -1)
return new BytecodeTypeAccess(packageName, typeName);
else
return new TypeAccess(packageName, typeName);
}
// Declared in BytecodeReader.jrag at line 385
public static Modifiers modifiers(int flags) {
Modifiers m = new Modifiers();
if ((flags & 0x0001) != 0)
m.addModifier(new Modifier("public"));
if ((flags & 0x0002) != 0)
m.addModifier(new Modifier("private"));
if ((flags & 0x0004) != 0)
m.addModifier(new Modifier("protected"));
if ((flags & 0x0008) != 0)
m.addModifier(new Modifier("static"));
if ((flags & 0x0010) != 0)
m.addModifier(new Modifier("final"));
if ((flags & 0x0020) != 0)
m.addModifier(new Modifier("synchronized"));
if ((flags & 0x0040) != 0)
m.addModifier(new Modifier("volatile"));
if ((flags & 0x0080) != 0)
m.addModifier(new Modifier("transient"));
if ((flags & 0x0100) != 0)
m.addModifier(new Modifier("native"));
if ((flags & 0x0400) != 0)
m.addModifier(new Modifier("abstract"));
if ((flags & 0x0800) != 0)
m.addModifier(new Modifier("strictfp"));
return m;
}
// Declared in BytecodeReader.jrag at line 412
public void parseFields(TypeDecl typeDecl) {
int count = u2();
if(BytecodeParser.VERBOSE)
println("Fields (" + count + "):");
for (int i = 0; i < count; i++) {
if(BytecodeParser.VERBOSE)
print(" Field nbr " + i + " ");
FieldInfo fieldInfo = new FieldInfo(this);
if(!fieldInfo.isSynthetic())
typeDecl.addBodyDecl(fieldInfo.bodyDecl());
}
}
// Declared in BytecodeReader.jrag at line 426
public void parseMethods(TypeDecl typeDecl) {
int count = u2();
if(BytecodeParser.VERBOSE)
println("Methods (" + count + "):");
for (int i = 0; i < count; i++) {
if(BytecodeParser.VERBOSE)
print(" Method nbr " + i + " ");
MethodInfo info = new MethodInfo(this);
if(!info.isSynthetic() && !info.name.equals("<clinit>")) {
typeDecl.addBodyDecl(info.bodyDecl());
}
}
}
// Declared in BytecodeReader.jrag at line 441
public CONSTANT_Info[] constantPool = null;
// Declared in BytecodeReader.jrag at line 443
private void checkLengthAndNull(int index) {
if(index >= constantPool.length) {
throw new Error("Trying to access element " + index + " in constant pool of length " + constantPool.length);
}
if(constantPool[index] == null)
throw new Error("Unexpected null element in constant pool at index " + index);
}
// Declared in BytecodeReader.jrag at line 450
public boolean validConstantPoolIndex(int index) {
return index < constantPool.length && constantPool[index] != null;
}
// Declared in BytecodeReader.jrag at line 453
public CONSTANT_Info getCONSTANT_Info(int index) {
checkLengthAndNull(index);
return constantPool[index];
}
// Declared in BytecodeReader.jrag at line 457
public CONSTANT_Utf8_Info getCONSTANT_Utf8_Info(int index) {
checkLengthAndNull(index);
CONSTANT_Info info = constantPool[index];
if(!(info instanceof CONSTANT_Utf8_Info))
throw new Error("Expected CONSTANT_Utf8_info at " + index + " in constant pool but found " + info.getClass().getName());
return (CONSTANT_Utf8_Info)info;
}
// Declared in BytecodeReader.jrag at line 464
public CONSTANT_Class_Info getCONSTANT_Class_Info(int index) {
checkLengthAndNull(index);
CONSTANT_Info info = constantPool[index];
if(!(info instanceof CONSTANT_Class_Info))
throw new Error("Expected CONSTANT_Class_info at " + index + " in constant pool but found " + info.getClass().getName());
return (CONSTANT_Class_Info)info;
}
// Declared in BytecodeReader.jrag at line 472
public void parseConstantPool() {
int count = u2();
if(BytecodeParser.VERBOSE)
println("constant_pool_count: " + count);
constantPool = new CONSTANT_Info[count + 1];
for (int i = 1; i < count; i++) {
parseEntry(i);
if (constantPool[i] instanceof CONSTANT_Long_Info
|| constantPool[i] instanceof CONSTANT_Double_Info)
i++;
}
//println("ConstantPool: ");
//for(int i = 1; i < count; i++) {
// println(i + ", " + constantPool[i]);
//}
}
// Declared in BytecodeReader.jrag at line 491
private static final int CONSTANT_Class = 7;
// Declared in BytecodeReader.jrag at line 492
private static final int CONSTANT_FieldRef = 9;
// Declared in BytecodeReader.jrag at line 493
private static final int CONSTANT_MethodRef = 10;
// Declared in BytecodeReader.jrag at line 494
private static final int CONSTANT_InterfaceMethodRef = 11;
// Declared in BytecodeReader.jrag at line 495
private static final int CONSTANT_String = 8;
// Declared in BytecodeReader.jrag at line 496
private static final int CONSTANT_Integer = 3;
// Declared in BytecodeReader.jrag at line 497
private static final int CONSTANT_Float = 4;
// Declared in BytecodeReader.jrag at line 498
private static final int CONSTANT_Long = 5;
// Declared in BytecodeReader.jrag at line 499
private static final int CONSTANT_Double = 6;
// Declared in BytecodeReader.jrag at line 500
private static final int CONSTANT_NameAndType = 12;
// Declared in BytecodeReader.jrag at line 501
private static final int CONSTANT_Utf8 = 1;
// Declared in BytecodeReader.jrag at line 503
public void parseEntry(int i) {
int tag = u1();
switch (tag) {
case CONSTANT_Class:
constantPool[i] = new CONSTANT_Class_Info(this);
break;
case CONSTANT_FieldRef:
constantPool[i] = new CONSTANT_Fieldref_Info(this);
break;
case CONSTANT_MethodRef:
constantPool[i] = new CONSTANT_Methodref_Info(this);
break;
case CONSTANT_InterfaceMethodRef:
constantPool[i] = new CONSTANT_InterfaceMethodref_Info(this);
break;
case CONSTANT_String:
constantPool[i] = new CONSTANT_String_Info(this);
break;
case CONSTANT_Integer:
constantPool[i] = new CONSTANT_Integer_Info(this);
break;
case CONSTANT_Float:
constantPool[i] = new CONSTANT_Float_Info(this);
break;
case CONSTANT_Long:
constantPool[i] = new CONSTANT_Long_Info(this);
break;
case CONSTANT_Double:
constantPool[i] = new CONSTANT_Double_Info(this);
break;
case CONSTANT_NameAndType:
constantPool[i] = new CONSTANT_NameAndType_Info(this);
break;
case CONSTANT_Utf8:
constantPool[i] = new CONSTANT_Utf8_Info(this);
break;
default:
println("Unknown entry: " + tag);
}
}
}