Skip to content

Commit

Permalink
refactored bytecode signature classes
Browse files Browse the repository at this point in the history
  • Loading branch information
Cornul11 committed Jul 1, 2023
1 parent 4714a16 commit d14b11b
Show file tree
Hide file tree
Showing 17 changed files with 298 additions and 160 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import nl.tudelft.cornul11.thesis.file.ClassFileInfo;
import nl.tudelft.cornul11.thesis.signature.extractor.bytecode.BytecodeDetails;
import nl.tudelft.cornul11.thesis.signature.extractor.bytecode.BytecodeParser;
import nl.tudelft.cornul11.thesis.signature.extractor.bytecode.BytecodeUtils;
import nl.tudelft.cornul11.thesis.util.ConfigurationLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -173,7 +174,7 @@ private ClassFileInfo processClassFile(JarEntry entry, JarFile jarFile) throws I
try (InputStream classFileInputStream = jarFile.getInputStream(entry)) {
byte[] bytecode = classFileInputStream.readAllBytes();
BytecodeDetails bytecodeDetails = BytecodeParser.extractSignature(bytecode);
return new ClassFileInfo(entry.getName(), bytecodeDetails.getSignature());
return new ClassFileInfo(entry.getName(), BytecodeUtils.getSignatureHash(bytecodeDetails));
} catch (Exception e) {
logger.error("Error while processing class file: " + entry.getName(), e);
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import nl.tudelft.cornul11.thesis.file.LibraryMatchInfo;
import nl.tudelft.cornul11.thesis.signature.extractor.bytecode.BytecodeDetails;
import nl.tudelft.cornul11.thesis.signature.extractor.bytecode.BytecodeParser;
import nl.tudelft.cornul11.thesis.signature.extractor.bytecode.BytecodeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -88,7 +89,7 @@ private ClassFileInfo processClassFile(JarEntry entry, JarFile jarFile) throws I
byte[] bytecode = classFileInputStream.readAllBytes();
BytecodeDetails bytecodeDetails = BytecodeParser.extractSignature(bytecode);
// TODO: jsr305 is always the same
return new ClassFileInfo(entry.getName(), bytecodeDetails.getSignature());
return new ClassFileInfo(entry.getName(), BytecodeUtils.getSignatureHash(bytecodeDetails));
} catch (Exception e) {
logger.error("Error while processing class file: " + entry.getName(), e);
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,31 +19,31 @@ public void visit(String name, Object value) {
if (value instanceof String) {
value = BytecodeUtils.getShortName((String) value);
}
annotation.arguments.put(name, value);
annotation.putArgument(name, value);
super.visit(name, value);
}

@Override
public AnnotationVisitor visitArray(String name) {
name = BytecodeUtils.getShortName(name);
List<Object> values = new ArrayList<>();
annotation.arrayArguments.put(name, values);
annotation.putArrayArgument(name, values);
return new BytecodeArrayAnnotationVisitor(api, super.visitArray(name), values);
}

@Override
public AnnotationVisitor visitAnnotation(String name, String desc) {
AnnotationDetails nestedAnnotation = new AnnotationDetails();
nestedAnnotation.desc = BytecodeUtils.getShortDesc(desc);
annotation.annotationArguments.put(name, nestedAnnotation);
desc = BytecodeUtils.getShortDesc(desc);
AnnotationDetails nestedAnnotation = new AnnotationDetails(desc, null);
annotation.putAnnotationArgument(name, nestedAnnotation);
return new BytecodeAnnotationVisitor(api, super.visitAnnotation(name, desc), nestedAnnotation);
}

@Override
public void visitEnum(String name, String desc, String value) {
desc = BytecodeUtils.getShortDesc(desc);
value = BytecodeUtils.getShortName(value);
annotation.arguments.put(name, desc + "." + value);
annotation.putArgument(name, desc + "." + value);
super.visitEnum(name, desc, value);
}
}
Original file line number Diff line number Diff line change
@@ -1,74 +1,56 @@
package nl.tudelft.cornul11.thesis.signature.extractor.bytecode;

import nl.tudelft.cornul11.thesis.signature.extractor.bytecode.members.*;
import org.objectweb.asm.*;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;

import java.util.Arrays;
import java.util.stream.Collectors;

import static org.objectweb.asm.Opcodes.ASM9;

public class BytecodeClassVisitor extends ClassVisitor {
private final BytecodeDetails bytecodeDetails = new BytecodeDetails();
private final BytecodeDetails.Builder bytecodeDetailsBuilder = new BytecodeDetails.Builder();

public BytecodeClassVisitor() {
super(ASM9);
}

public BytecodeDetails getBytecodeClass() {
return bytecodeDetails;
return bytecodeDetailsBuilder.build();
}

public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
bytecodeDetails.name = BytecodeUtils.getShortName(name);
bytecodeDetails.extendsType = BytecodeUtils.getShortName(superName);
bytecodeDetails.interfaces = Arrays.stream(interfaces).map(BytecodeUtils::getShortName).collect(Collectors.toList());
bytecodeDetailsBuilder.setName(BytecodeUtils.getShortName(name));
bytecodeDetailsBuilder.setAccess(access);
bytecodeDetailsBuilder.setExtendsType(BytecodeUtils.getShortName(superName));
Arrays.stream(interfaces).map(BytecodeUtils::getShortName).map(bytecodeDetailsBuilder::addInterface);
super.visit(version, access, name, signature, superName, interfaces);
}

public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
desc = BytecodeUtils.getShortDesc(desc);

AnnotationDetails annotationDetails = new AnnotationDetails();
annotationDetails.desc = desc;
annotationDetails.visible = visible;
bytecodeDetails.annotations.add(annotationDetails);
AnnotationDetails annotationDetails = new AnnotationDetails(desc, visible);
bytecodeDetailsBuilder.addAnnotation(annotationDetails);

AnnotationVisitor av = super.visitAnnotation(desc, visible);
return new BytecodeAnnotationVisitor(ASM9, av, annotationDetails);
}

public void visitInnerClass(String name, String outerName, String innerName, int access) {
name = BytecodeUtils.getShortName(name);
if (outerName != null)
outerName = BytecodeUtils.getShortName(outerName);

NestedClassDetails nestedClassDetails = new NestedClassDetails();
nestedClassDetails.name = name;
nestedClassDetails.outerName = outerName;
nestedClassDetails.innerName = innerName;
nestedClassDetails.access = access;

if ((access & Opcodes.ACC_INTERFACE) != 0) {
nestedClassDetails.type = "INTERFACE";
} else if ((access & Opcodes.ACC_ENUM) != 0) {
nestedClassDetails.type = "ENUM";
} else if ((access & Opcodes.ACC_STATIC) != 0) {
nestedClassDetails.type = "STATIC_CLASS";
} else {
nestedClassDetails.type = "INNER_CLASS";
}

bytecodeDetails.innerClasses.add(nestedClassDetails);
outerName = outerName != null ? BytecodeUtils.getShortName(outerName) : null;
NestedClassDetails nestedClassDetails = new NestedClassDetails(name, outerName, innerName, access);
bytecodeDetailsBuilder.addInnerClass(nestedClassDetails);
}

public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
desc = BytecodeUtils.getShortDesc(desc);

FieldDetails fieldDetails = new FieldDetails();
fieldDetails.name = name;
fieldDetails.desc = desc;
bytecodeDetails.fields.add(fieldDetails);
FieldDetails fieldDetails = new FieldDetails(name, desc);
bytecodeDetailsBuilder.addField(fieldDetails);

FieldVisitor originalVisitor = super.visitField(access, name, desc, signature, value);
return new BytecodeFieldVisitor(api, originalVisitor, fieldDetails);
Expand All @@ -77,28 +59,19 @@ public FieldVisitor visitField(int access, String name, String desc, String sign
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
desc = BytecodeUtils.getShortDesc(desc);
signature = signature != null ? BytecodeUtils.getShortDesc(signature) : null;
exceptions = exceptions != null ? Arrays.stream(exceptions).map(BytecodeUtils::getShortName).toArray(String[]::new) : null;

MethodDetails method = new MethodDetails();
method.access = access;
method.name = name;
method.setDesc(desc);
method.signature = signature;
method.exceptions = exceptions != null ? Arrays.stream(exceptions).map(BytecodeUtils::getShortName).toArray(String[]::new) : null;

MethodDetails method = null;
if ("<init>".equals(name)) {
// This is a constructor
ConstructorDetails constructor = new ConstructorDetails();
constructor.name = name;
constructor.desc = desc;
constructor.signature = signature;
constructor.exceptions = exceptions != null ? Arrays.stream(exceptions).map(BytecodeUtils::getShortName).toArray(String[]::new) : null;
bytecodeDetails.constructors.add(constructor);
ConstructorDetails constructor = new ConstructorDetails(name, desc, signature, exceptions);
bytecodeDetailsBuilder.addConstructor(constructor);
} else {
// This is a method
bytecodeDetails.methods.add(method);
method = new MethodDetails(access, name, desc, signature, exceptions);
bytecodeDetailsBuilder.addMethod(method);
}

MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
return new BytecodeMethodVisitor(ASM9, mv, method);
return method != null ? new BytecodeMethodVisitor(ASM9, mv, method) : mv;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,42 +7,118 @@
import java.util.List;

public class BytecodeDetails {
public String name;
public String extendsType;
public List<String> interfaces = new ArrayList<>();
public List<FieldDetails> fields = new ArrayList<>();
public List<MethodDetails> methods = new ArrayList<>();
public List<ConstructorDetails> constructors = new ArrayList<>();
public List<NestedClassDetails> innerClasses = new ArrayList<>();
public List<AnnotationDetails> annotations = new ArrayList<>();


//
// private void preProcessNames() {
// for (AnnotationDetails annotation : annotations) {
// for (Map.Entry<String, AnnotationDetails> entry : annotation.annotationArguments.entrySet()) {
// entry.getValue().desc = getShortDesc(entry.getValue().desc);
// }
// }
//
// // Similar processing should be done for the names inside innerInterfaces, innerEnums, and annotations
// }
public long getSignature() {
// TODO: move the hashing function outside of this class
// this function should only return the signature, not hash it

LongHashFunction cityHashFunction = LongHashFunction.xx3();
StringBuilder classSignature = new StringBuilder();

// Considering the name is now shortened (loses package name), we can add it to the signature
classSignature.append(name);
classSignature.append(extendsType);
classSignature.append(interfaces.toString());
classSignature.append(fields.toString());
classSignature.append(methods.toString());
classSignature.append(constructors.toString());
classSignature.append(innerClasses.toString());
classSignature.append(annotations.toString());
return cityHashFunction.hashChars(classSignature);
private int access;
private String name;
private String extendsType;
private List<String> interfaces = new ArrayList<>();
private List<FieldDetails> fields = new ArrayList<>();
private List<MethodDetails> methods = new ArrayList<>();
private List<ConstructorDetails> constructors = new ArrayList<>();
private List<NestedClassDetails> innerClasses = new ArrayList<>();
private List<AnnotationDetails> annotations = new ArrayList<>();

private BytecodeDetails(Builder builder) {
this.access = builder.access;
this.name = builder.name;
this.extendsType = builder.extendsType;
this.interfaces = builder.interfaces;
this.fields = builder.fields;
this.methods = builder.methods;
this.constructors = builder.constructors;
this.innerClasses = builder.innerClasses;
this.annotations = builder.annotations;
}

public String getName() {
return name;
}

public String getExtendsType() {
return extendsType;
}

public List<String> getInterfaces() {
return interfaces;
}

public List<FieldDetails> getFields() {
return fields;
}

public List<MethodDetails> getMethods() {
return methods;
}

public List<ConstructorDetails> getConstructors() {
return constructors;
}

public List<NestedClassDetails> getInnerClasses() {
return innerClasses;
}

public List<AnnotationDetails> getAnnotations() {
return annotations;
}

public static class Builder {
private int access;
private String name;
private String extendsType;
private List<String> interfaces = new ArrayList<>();
private List<FieldDetails> fields = new ArrayList<>();
private List<MethodDetails> methods = new ArrayList<>();
private List<ConstructorDetails> constructors = new ArrayList<>();
private List<NestedClassDetails> innerClasses = new ArrayList<>();
private List<AnnotationDetails> annotations = new ArrayList<>();

public Builder setName(String name) {
this.name = name;
return this;
}

public Builder setExtendsType(String extendsType) {
this.extendsType = extendsType;
return this;
}

public Builder addInterface(String interfaceName) {
this.interfaces.add(interfaceName);
return this;
}

public Builder addField(FieldDetails field) {
this.fields.add(field);
return this;
}

public Builder addMethod(MethodDetails method) {
this.methods.add(method);
return this;
}

public Builder addConstructor(ConstructorDetails constructor) {
this.constructors.add(constructor);
return this;
}

public Builder addInnerClass(NestedClassDetails innerClass) {
this.innerClasses.add(innerClass);
return this;
}

public Builder addAnnotation(AnnotationDetails annotation) {
this.annotations.add(annotation);
return this;
}

public Builder setAccess(int access) {
this.access = access;
return this;
}

public BytecodeDetails build() {
return new BytecodeDetails(this);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ public BytecodeFieldVisitor(int api, FieldVisitor fieldVisitor, FieldDetails fie
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
desc = BytecodeUtils.getShortDesc(desc);
AnnotationDetails annotation = new AnnotationDetails();
annotation.desc = desc;
field.annotations.add(annotation);
AnnotationDetails annotation = new AnnotationDetails(desc, visible);
field.addAnnotation(annotation);
return new BytecodeAnnotationVisitor(api, super.visitAnnotation(desc, visible), annotation);
}
}
Loading

0 comments on commit d14b11b

Please sign in to comment.