Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Submission instrumentation #151

Draft
wants to merge 52 commits into
base: master
Choose a base branch
from
Draft
Changes from 1 commit
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
4858461
Add prototype for full project instrumentation
Hapstyx Nov 15, 2024
3e3e7b1
Add more documentation
Hapstyx Nov 17, 2024
9656943
Refactoring
Hapstyx Nov 17, 2024
ce09349
Add configuration options
Hapstyx Nov 17, 2024
6e0a0fe
Add more missing documentation
Hapstyx Nov 17, 2024
a3f4cbf
Fixes and refactoring
Hapstyx Nov 18, 2024
c545b48
Implement constructor substitution
Hapstyx Nov 18, 2024
cd102da
Record stack trace in invocation
Hapstyx Nov 19, 2024
35a7d24
Implement method call replacement
Hapstyx Nov 19, 2024
ebfbde1
Refactoring
Hapstyx Nov 19, 2024
c8c2e90
Refactor method calling instructions
Hapstyx Nov 20, 2024
390c102
Fix method signature for getOriginalFieldHeaders and getOrignalMethod…
Hapstyx Nov 21, 2024
f5ba418
Filter synthetic fields and methods from original headers
Hapstyx Nov 21, 2024
b256ed4
Fix NPE in SolutionClassNode
Hapstyx Nov 21, 2024
8185233
Fix bug where submission class was loaded from wrong class loader
Hapstyx Nov 23, 2024
3fe4a44
Use submission-info.json for finding submission classes
Hapstyx Nov 26, 2024
23b5c45
Fixes and refactoring
Hapstyx Nov 26, 2024
3ad6919
Make framework more robust for incompatible fields and methods (stati…
Hapstyx Nov 26, 2024
9bc6a86
Simplify header replication
Hapstyx Nov 27, 2024
98111aa
Allow defining alternative names for solution class matching
Hapstyx Nov 28, 2024
d2d1a89
Refactoring, documentation, etc.
Hapstyx Nov 29, 2024
44e2e74
Create separate exception for irrecoverable header mismatches
Hapstyx Nov 30, 2024
d5bcfa6
Refactor SimilarityMatcher and prevent duplicates
Hapstyx Nov 30, 2024
09aec1e
Allow targeting specific methods for disabling logging, substitution …
Hapstyx Nov 30, 2024
a645cfe
Allow calling the original method from substituted methods
Hapstyx Nov 30, 2024
71721e2
Current state
Hapstyx Dec 3, 2024
527fa06
Refactor method visitors
Hapstyx Dec 3, 2024
c61bf01
Add mechanism for injecting missing classes
Hapstyx Dec 3, 2024
860b077
Remove locals from injected methods since they're static
Hapstyx Dec 3, 2024
2d74300
Refactoring and enable injecting missing classes into Jagr
Hapstyx Dec 3, 2024
c509df6
Small fixes and some refactoring
Hapstyx Dec 4, 2024
d300496
Add missing documentation
Hapstyx Dec 4, 2024
f52c3f1
Rework SubmissionExecutionHandler API
Hapstyx Dec 5, 2024
528db93
Add some utility method to the header classes
Hapstyx Dec 5, 2024
b350bac
Improve similarity matching for classes and their members
Hapstyx Dec 5, 2024
f8f6e33
Re-add accidentally deleted methods
Hapstyx Dec 5, 2024
3a836d5
Small fixes
Hapstyx Dec 5, 2024
306fb7f
Some more fixes
Hapstyx Dec 6, 2024
aaf0971
Move headers classes to own package
Hapstyx Dec 6, 2024
276834d
Rename getType() => getHeaderType() in header classes
Hapstyx Dec 6, 2024
b1f6fce
Add methods to get the class representations for the different types
Hapstyx Dec 6, 2024
df73861
Add method to check type category
Hapstyx Dec 8, 2024
a363114
Add some more convenience methods
Hapstyx Dec 8, 2024
7574bb9
Enable invocation injection to work with the stack
Hapstyx Dec 8, 2024
e0c5929
Fix small bug in SolutionClassNode
Hapstyx Dec 8, 2024
72c4a49
Save original enum constants to be retrieved later
Hapstyx Dec 8, 2024
8c743ab
Save original static field values to be retrieved later
Hapstyx Dec 8, 2024
e95c3ba
More bug fixes
Hapstyx Dec 9, 2024
aac3a46
Add convenience methods for getting and setting field values
Hapstyx Dec 16, 2024
2b8cb96
Fix static field replacement
Hapstyx Dec 16, 2024
1a62608
fix stringifier for primitive arrays (#155)
FussballAndy Dec 17, 2024
ee8ef46
require java 21
Rdeisenroth Jan 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Record stack trace in invocation
Hapstyx committed Nov 19, 2024
commit cd102dade07085bc0c45e757c64be018739156d2
Original file line number Diff line number Diff line change
@@ -156,6 +156,7 @@ public MethodVisitor visitMethod(int access, String name, String descriptor, Str
Type stringType = Type.getType(String.class);
Type submissionExecutionHandlerType = SubmissionExecutionHandler.INTERNAL_TYPE;
Type sehInternalType = SubmissionExecutionHandler.Internal.INTERNAL_TYPE;
Type invocationType = Invocation.INTERNAL_TYPE;
Type methodSubstitutionType = MethodSubstitution.INTERNAL_TYPE;
Type constructorBehaviourType = MethodSubstitution.ConstructorBehaviour.INTERNAL_TYPE;

@@ -255,7 +256,7 @@ public void visitCode() {
super.visitMethodInsn(INVOKEVIRTUAL,
sehInternalType.getInternalName(),
"addInvocation",
Type.getMethodDescriptor(Type.VOID_TYPE, methodHeader.getType(), Invocation.INTERNAL_TYPE),
Type.getMethodDescriptor(Type.VOID_TYPE, methodHeader.getType(), invocationType),
false);
}

@@ -391,7 +392,7 @@ public void visitCode() {
super.visitMethodInsn(INVOKEINTERFACE,
methodSubstitutionType.getInternalName(),
"execute",
Type.getMethodDescriptor(objectType, Invocation.INTERNAL_TYPE),
Type.getMethodDescriptor(objectType, invocationType),
true);
Type returnType = Type.getReturnType(methodHeader.descriptor());
if (returnType.getSort() == Type.ARRAY || returnType.getSort() == Type.OBJECT) {
@@ -571,31 +572,54 @@ public void visitMethodInsn(int opcode, String owner, String name, String descri
* @param argumentTypes an array of parameter types
*/
private void buildInvocation(Type[] argumentTypes) {
super.visitTypeInsn(NEW, Invocation.INTERNAL_TYPE.getInternalName());
Type threadType = Type.getType(Thread.class);
Type stackTraceElementArrayType = Type.getType(StackTraceElement[].class);

super.visitTypeInsn(NEW, invocationType.getInternalName());
super.visitInsn(DUP);
if (!isStatic && !isConstructor) {
super.visitVarInsn(ALOAD, 0);
super.visitMethodInsn(INVOKESTATIC,
threadType.getInternalName(),
"currentThread",
Type.getMethodDescriptor(threadType),
false);
super.visitMethodInsn(INVOKEVIRTUAL,
threadType.getInternalName(),
"getStackTrace",
Type.getMethodDescriptor(stackTraceElementArrayType),
false);
super.visitMethodInsn(INVOKESPECIAL,
Invocation.INTERNAL_TYPE.getInternalName(),
invocationType.getInternalName(),
"<init>",
"(Ljava/lang/Object;)V",
Type.getMethodDescriptor(Type.VOID_TYPE, objectType, stackTraceElementArrayType),
false);
} else {
super.visitMethodInsn(INVOKESTATIC,
threadType.getInternalName(),
"currentThread",
Type.getMethodDescriptor(threadType),
false);
super.visitMethodInsn(INVOKEVIRTUAL,
threadType.getInternalName(),
"getStackTrace",
Type.getMethodDescriptor(stackTraceElementArrayType),
false);
super.visitMethodInsn(INVOKESPECIAL,
Invocation.INTERNAL_TYPE.getInternalName(),
invocationType.getInternalName(),
"<init>",
"()V",
Type.getMethodDescriptor(Type.VOID_TYPE, stackTraceElementArrayType),
false);
}
// load parameter with opcode (ALOAD, ILOAD, etc.) for type and ignore "this", if it exists
for (int i = 0; i < argumentTypes.length; i++) {
super.visitInsn(DUP);
// load parameter with opcode (ALOAD, ILOAD, etc.) for type and ignore "this", if it exists
super.visitVarInsn(argumentTypes[i].getOpcode(ILOAD), getLocalsIndex(argumentTypes, i) + (isStatic ? 0 : 1));
boxType(getDelegate(), argumentTypes[i]);
super.visitMethodInsn(INVOKEVIRTUAL,
Invocation.INTERNAL_TYPE.getInternalName(),
invocationType.getInternalName(),
"addParameter",
"(Ljava/lang/Object;)V",
Type.getMethodDescriptor(Type.VOID_TYPE, objectType),
false);
}
}
Original file line number Diff line number Diff line change
@@ -9,29 +9,36 @@

/**
* This class holds information about the context of an invocation.
* Context means the object a method was invoked on and the parameters it was invoked with.
* Context means the object a method was invoked on and the parameters it was invoked with
* as well as the stack trace up to the point of invocation.
* @author Daniel Mangold
*/
public class Invocation {

public static final Type INTERNAL_TYPE = Type.getType(Invocation.class);

private final Object instance;
private final StackTraceElement[] stackTrace;
private final List<Object> parameterValues = new ArrayList<>();

/**
* Constructs a new invocation.
*
* @param stackTrace the stack trace up to the point of invocation
*/
public Invocation() {
this(null);
public Invocation(StackTraceElement[] stackTrace) {
this(null, stackTrace);
}

/**
* Constructs a new invocation.
*
* @param instance the object on which this invocation takes place
* @param instance the object on which this invocation takes place
* @param stackTrace the stack trace up to the point of invocation
*/
public Invocation(Object instance) {
public Invocation(Object instance, StackTraceElement[] stackTrace) {
this.instance = instance;
this.stackTrace = stackTrace;
}

/**
@@ -43,6 +50,19 @@ public Object getInstance() {
return instance;
}

/**
* Returns the stack trace up to the point of this method's invocation.
*
* @return the stack trace
*/
public StackTraceElement[] getStackTrace() {
return stackTrace;
}

public StackTraceElement getCallerStackTraceElement() {
return stackTrace[1];
}

/**
* Returns the list of parameter values the method was invoked with.
*