...
 
Commits (4)
......@@ -55,3 +55,11 @@ test shvm:
policy: pull
script:
- ant test-shvm
test util:
stage: test
cache:
<<: *cache
policy: pull
script:
- ant test-util
......@@ -4,7 +4,7 @@ src.shvm=src-shvm
src.shvm.agent=src-shvm-agent
src.shvm.dispatch=src-shvm-dispatch
src.test=src-test
src.util=src-util
src.util=util/src
src.tools=src-tools
src.doc=doc
src.doc.jdoc=${src.doc}/javadoc
......
......@@ -262,7 +262,7 @@
<!-- Project class paths -->
<path id="util.classpath">
<pathelement location="${build.util}"/>
<pathelement location="${src.util.prefix}/${build.util}"/>
</path>
<path id="disl.classpath">
......@@ -456,11 +456,7 @@
<!-- Shared utility code -->
<target name="compile-util" depends="-init">
<mkdir dir="${build.util}"/>
<javac destdir="${build.util}" srcdir="${src.util}" debug="true">
<classpath refid="asm.classpath"/>
<classpath refid="log4j.classpath"/>
</javac>
<ant dir="${src.util.prefix}" target="compile" usenativebasedir="true" />
<!-- Register logging providers -->
<!--
......@@ -532,7 +528,7 @@
the necessary bytecode.
-->
<target name="-check-disl-agent-bytecode">
<property name="build.disl.agent.bytecode.path" value="${src.disl.agent}/bytecode.c"/>
<property name="build.disl.agent.bytecode.path" value="${src.shvm.agent}/disl/bytecode.c"/>
<uptodate property="build.disl.agent.bytecode.uptodate" targetfile="${build.disl.agent.bytecode.path}">
<srcfiles dir="${src.disl.bypass}"/>
</uptodate>
......@@ -786,8 +782,13 @@
<ant antfile="${src.shvm.prefix}/build.xml" target="test" usenativebasedir="true" />
</target>
<!-- Run the shadow VM unit tests -->
<target name="test-util">
<ant antfile="${src.util.prefix}/build.xml" target="test" usenativebasedir="true" />
</target>
<!-- Run all tests -->
<target name="test" depends="test-disl,test-shvm,test-compound"></target>
<target name="test" depends="test-disl,test-shvm,test-util,test-compound"></target>
<!-- Run compound tests -->
<target name="test-compound" depends="build,build-test" description="Runs all tests or a selected (-Dtest.name=...) test suite.">
......@@ -827,7 +828,7 @@
<path refid="asm.classpath"/>
<path refid="junit.classpath"/>
<pathelement location="${build.test}"/>
<pathelement location="${build.util}"/>
<pathelement location="${src.util.prefix}/${build.util}" />
<pathelement location="${src.disl-server.prefix}/${build.disl-server}" />
<pathelement location="${src.shvm-server.prefix}/${build.shvm-server}" />
<pathelement location="${src.disl.prefix}/${build.disl}"/>
......@@ -1073,6 +1074,7 @@
<ant dir="${src.shvm.prefix}" target="clean" />
<ant dir="${src.disl-server.prefix}" target="clean" />
<ant dir="${src.disl.prefix}" target="clean" />
<ant dir="${src.util.prefix}" target="clean" />
<exec executable="make" dir="${src.disl.agent}">
<arg value="cleanall"/>
......
......@@ -20,6 +20,7 @@ src.disl.prefix=disl
src.disl-server.prefix=disl-server
src.shvm.prefix=shvm
src.shvm-server.prefix=shvm-server
src.util.prefix=util
disl.lib=disl-server.jar
shvm-server.lib=dislre-server.jar
......
......@@ -21,7 +21,7 @@
<fileset dir="../${lib.disl.dir}" includes="asm*.jar" id="asm.fileset"/>
</path>
<path id="util.classpath">
<pathelement location="../${build.util}"/>
<pathelement location="../${src.util.prefix}/${build.util}"/>
</path>
<path id="protobuf.classpath">
......@@ -82,7 +82,7 @@
<service type="javax.annotation.processing.Processor" provider="ch.usi.dag.disl.DislClassFinder"/>
<fileset dir="${build.disl-server}" />
<fileset dir="../${build.util}"/>
<fileset dir="../${src.util.prefix}/${build.util}"/>
<fileset dir="../${src.disl.prefix}/${build.disl}"/>
<resources refid="disl.bypass.files"/>
</jar>
......
......@@ -14,7 +14,7 @@
</path>
<path id="util.classpath">
<pathelement location="../${build.util}"/>
<pathelement location="../${src.util.prefix}/${build.util}"/>
</path>
<path id="junit.classpath">
......@@ -94,9 +94,9 @@
<classpath>
<path refid="asm.classpath"/>
<path refid="junit.classpath"/>
<path refid="util.classpath"/>
<path path="${build.disl.test}"/>
<path path="../${build.util}"/>
<path path="${build.disl}"/>
</classpath>
......
......@@ -5,3 +5,5 @@ instrumentation, only the analysis is performed.
Its only functionality is to receive the analysis requests and pass them to the
shvm object model library.
Main package is `ch.usi.dag.reserver`
......@@ -21,7 +21,7 @@
<fileset dir="../${lib.disl.dir}" includes="asm*.jar" id="asm.fileset"/>
</path>
<path id="util.classpath">
<pathelement location="../${build.util}"/>
<pathelement location="../${src.util.prefix}/${build.util}"/>
</path>
<path id="protobuf.classpath">
......@@ -74,13 +74,13 @@
<jar destfile="${out.lib}/${shvm-server.lib}">
<manifest>
<attribute name="Class-Path" value="${asm.libs} ${protobuf.libs}"/>
<attribute name="Main-Class" value="ch.usi.dag.dislreserver.DiSLREServer"/>
<attribute name="Main-Class" value="ch.usi.dag.reserver.REServer"/>
<attribute name="DiSL-Version" value="${disl.version}"/>
</manifest>
<fileset dir="${build.shvm-server}" />
<fileset dir="../${src.shvm.prefix}/${build.shvm}" />
<fileset dir="../${build.util}"/>
<fileset dir="../${src.util.prefix}/${build.util}"/>
</jar>
</target>
......
This diff is collapsed.
/**
* Logging methods extracted from DiSLREServer class
* Logging methods extracted from REServer class
*
* Author: Vit Kabele <vit@kabele.me>
* Created on the 21/02/2019
*/
package ch.usi.dag.dislreserver;
package ch.usi.dag.reserver;
import ch.usi.dag.shvm.DiSLREServerException;
import ch.usi.dag.util.logging.Logger;
import java.io.PrintWriter;
......@@ -13,7 +14,7 @@ import java.io.StringWriter;
/**
* Logging methods extracted from DiSLREServer class
* Logging methods extracted from REServer class
*/
abstract class Log {
......
package ch.usi.dag.dislreserver;
package ch.usi.dag.reserver;
import java.io.*;
import java.net.InetSocketAddress;
......@@ -11,10 +11,13 @@ import java.nio.channels.SocketChannel;
import ch.usi.dag.dislre.protocol.Main;
import ch.usi.dag.shvm.Logging;
import ch.usi.dag.shvm.SHVM;
import ch.usi.dag.shvm.SHVMImpl;
import ch.usi.dag.util.logging.Logger;
public abstract class DiSLREServer {
public abstract class REServer {
private static final Logger __log = Logging.getPackageInstance ();
......
package ch.usi.dag.dislreserver;
package ch.usi.dag.reserver;
import ch.usi.dag.dislre.protocol.Main.*;
import ch.usi.dag.dislre.protocol.Analysis.*;
import ch.usi.dag.shvm.DiSLREServerException;
import ch.usi.dag.shvm.SHVM;
import ch.usi.dag.util.logging.Logger;
import ch.usi.dag.util.ByteArrayUtils;
/**
......
......@@ -3,7 +3,9 @@
This is the ShadowVM object model. The core of the analysis. It only exposes
the public API defined in `src/src-server-api`
Main package is `ch.usi.dag.shvm`
## TODO
* Move the whole implementation into new package. Current is `ch.usi.dag.dislreserver`,
* Move the whole implementation into new package. Current is `ch.usi.dag.shvm`,
which does not makes a sense, since the object model is separated from the server.
......@@ -14,7 +14,7 @@
<fileset dir="../${lib.disl.dir}" includes="asm*.jar" id="asm.fileset"/>
</path>
<path id="util.classpath">
<pathelement location="../${build.util}"/>
<pathelement location="../${src.util.prefix}/${build.util}"/>
</path>
<path id="junit.classpath">
......@@ -79,9 +79,9 @@
<classpath>
<path refid="asm.classpath"/>
<path refid="junit.classpath"/>
<path refid="util.classpath"/>
<path path="${build.shvm.test}"/>
<path path="../${build.util}"/>
<path path="${build.shvm}"/>
</classpath>
......
package ch.usi.dag.dislreserver.shadow;
import ch.usi.dag.dislreserver.shadow.NetReferenceHelper;
import org.junit.Assert;
import org.junit.Test;
import org.junit.experimental.theories.Theories;
......
......@@ -12,9 +12,6 @@ import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import ch.usi.dag.dislreserver.shadow.FieldInfo;
import ch.usi.dag.dislreserver.shadow.MethodInfo;
import ch.usi.dag.dislreserver.shadow.ShadowClass;
import org.junit.Assert;
import org.junit.experimental.theories.PotentialAssignment;
import org.objectweb.asm.Type;
......
package ch.usi.dag.dislreserver;
package ch.usi.dag.shvm;
import java.util.Collections;
import java.util.concurrent.BlockingQueue;
......@@ -54,7 +54,7 @@ class ATEManager {
try {
endingExecutors.put(removedATE);
} catch (InterruptedException e) {
throw new DiSLREServerFatalException(
throw new DiSLREServerFatalException (
"Cannot add executor to the ending queue", e);
}
}
......
package ch.usi.dag.dislreserver;
package ch.usi.dag.shvm;
import java.util.List;
......@@ -81,7 +81,7 @@ class AnalysisDispatcher {
}
// NOTE: we are not updating the executor is ending state because
// whole shadow vm is ending
// whole shvm vm is ending
// wait for analysis threads
ateManager.waitForAllToEnd();
......@@ -96,7 +96,7 @@ class AnalysisDispatcher {
oftExec.join();
} catch (InterruptedException e) {
throw new DiSLREServerFatalException(
throw new DiSLREServerFatalException (
"Interrupted while waiting on obj free thread to finish",
e);
}
......
package ch.usi.dag.dislreserver;
package ch.usi.dag.shvm;
/**
* Thread processing analysis tasks
......@@ -30,7 +30,7 @@ class AnalysisThread extends Thread {
}
} catch (InterruptedException e) {
throw new DiSLREServerFatalException(
throw new DiSLREServerFatalException (
"Object free thread interupted while waiting on task", e);
}
}
......
package ch.usi.dag.dislreserver;
package ch.usi.dag.shvm;
import ch.usi.dag.dislreserver.remoteanalysis.RemoteAnalysis;
import ch.usi.dag.dislreserver.shadow.ShadowObject;
......@@ -19,7 +19,7 @@ class ObjectFreeTaskExecutor extends Thread {
private final BlockingQueue<ObjectFreeTask> taskQueue = new LinkedBlockingQueue<ObjectFreeTask>();
/**
* Current shadow VM context.
* Current shvm VM context.
*/
private final SHVMContext __shvmContext;
......@@ -52,11 +52,11 @@ class ObjectFreeTaskExecutor extends Thread {
private void invokeObjectFreeAnalysisHandlers(long objectFreeID) {
// TODO free events should be sent to analysis that sees the shadow object
// TODO free events should be sent to analysis that sees the shvm object
final ShadowObjectTable shadowObjectTable = __shvmContext.getShadowObjectTable ();
// retrieve shadow object
// retrieve shvm object
ShadowObject obj = shadowObjectTable.get(objectFreeID);
// get all analysis objects
......@@ -81,7 +81,7 @@ class ObjectFreeTaskExecutor extends Thread {
}
}
// release shadow object
// release shvm object
shadowObjectTable.freeShadowObject(obj);
}
......@@ -114,7 +114,7 @@ class ObjectFreeTaskExecutor extends Thread {
}
} catch (InterruptedException e) {
throw new DiSLREServerFatalException(
throw new DiSLREServerFatalException (
"Object free thread interupted while waiting on task", e);
}
}
......
package ch.usi.dag.dislreserver;
package ch.usi.dag.shvm;
import java.io.DataInputStream;
import java.io.IOException;
......@@ -6,7 +6,7 @@ import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;
import ch.usi.dag.dislreserver.AnalysisResolver.AnalysisMethodHolder;
import ch.usi.dag.shvm.AnalysisResolver.AnalysisMethodHolder;
import ch.usi.dag.dislreserver.shadow.ShadowObject;
import ch.usi.dag.util.logging.Logger;
......
package ch.usi.dag.dislreserver;
package ch.usi.dag.shvm;
import ch.usi.dag.dislreserver.remoteanalysis.RemoteAnalysis;
......@@ -68,7 +68,7 @@ final class AnalysisResolver {
/**
* Default constructor.
*
* @param shvmContext Current shadow VM context
* @param shvmContext Current shvm VM context
*/
AnalysisResolver(final SHVMContext shvmContext)
{
......
package ch.usi.dag.dislreserver;
package ch.usi.dag.shvm;
import java.io.DataInputStream;
import java.io.DataOutputStream;
......
package ch.usi.dag.dislreserver;
package ch.usi.dag.shvm;
public class DiSLREServerException extends Exception {
......
package ch.usi.dag.dislreserver;
package ch.usi.dag.shvm;
public class DiSLREServerFatalException extends RuntimeException {
......
......@@ -4,7 +4,7 @@
* Author: Vit Kabele <vit@kabele.me>
* Created on the 21/02/2019
*/
package ch.usi.dag.dislreserver;
package ch.usi.dag.shvm;
/**
* Public interface specifying the public API of ShadowVM object model.
......
......@@ -3,7 +3,7 @@
* Author: Vit Kabele <vit@kabele.me>
* Created on the 22/02/2019
*/
package ch.usi.dag.dislreserver;
package ch.usi.dag.shvm;
import ch.usi.dag.dislreserver.shadow.ShadowClassTable;
import ch.usi.dag.dislreserver.shadow.ShadowObjectTable;
......
......@@ -4,7 +4,7 @@
* Author: Vit Kabele <vit@kabele.me>
* Created on the 21/02/2019
*/
package ch.usi.dag.dislreserver;
package ch.usi.dag.shvm;
import java.io.*;
......@@ -43,7 +43,7 @@ public class SHVMImpl implements SHVM {
*
* @param logger
*/
SHVMImpl (
public SHVMImpl (
final Logger logger
) {
__log = logger;
......
......@@ -39,8 +39,8 @@ final class ObjectShadowClass extends ShadowClass {
if (object instanceof ShadowClass) {
//
// ShadowClass instances have no shadow class. If this shadow class
// represents the Object or Class types, then the other shadow class
// ShadowClass instances have no shvm class. If this shvm class
// represents the Object or Class types, then the other shvm class
// can be considered an instance of this type.
//
return __isObjectClass () || __isClassClass ();
......
......@@ -18,12 +18,12 @@ import org.objectweb.asm.Type;
public abstract class ShadowClass extends ShadowObject {
/**
* The type (class) represented by this shadow class.
* The type (class) represented by this shvm class.
*/
private final Type __type;
/**
* The class loader that loaded the class represented by this shadow class.
* The class loader that loaded the class represented by this shvm class.
* Will be {@code null} for primitive types (including {@code void}).
*/
private final ShadowObject __classLoader;
......@@ -64,7 +64,7 @@ public abstract class ShadowClass extends ShadowObject {
private boolean __equals (final ShadowClass other) {
//
// Two shadow classes are considered equal if they represent the
// Two shvm classes are considered equal if they represent the
// same type and have been loaded by the same class loader.
//
if (this.__type.equals (other.__type)) {
......@@ -104,7 +104,7 @@ public abstract class ShadowClass extends ShadowObject {
// TODO LB: Consider exposing a reference for the bootstrap class loader.
//
// This would diverge from the behavior of Java reflection API, but it
// would potentially allow an analysis to attach state to a shadow
// would potentially allow an analysis to attach state to a shvm
// object representing the bootstrap class loader. Not sure if it is
// necessary though.
//
......
......@@ -3,9 +3,9 @@ package ch.usi.dag.dislreserver.shadow;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import ch.usi.dag.dislreserver.DiSLREServerFatalException;
import ch.usi.dag.dislreserver.Logging;
import ch.usi.dag.dislreserver.SHVMContext;
import ch.usi.dag.shvm.DiSLREServerFatalException;
import ch.usi.dag.shvm.Logging;
import ch.usi.dag.shvm.SHVMContext;
import org.objectweb.asm.Type;
import ch.usi.dag.util.asm.ClassNodeHelper;
......@@ -34,38 +34,32 @@ public final class ShadowClassTable {
* a special object to use as a key into a map that returns a map of class
* names to class code.
*/
static final ShadowObject BOOTSTRAP_CLASSLOADER;
static final ShadowObject BOOTSTRAP_CLASSLOADER = new ShadowObject (0, null);
static final AtomicReference <ShadowClass> JAVA_LANG_CLASS;
static final AtomicReference <ShadowClass> JAVA_LANG_CLASS = new AtomicReference <> ();
private static final Type __JAVA_LANG_CLASS_TYPE__;
private final Type __JAVA_LANG_CLASS_TYPE__ = Type.getType (Class.class);
private final SHVMContext __shvmContext;
private static final ConcurrentHashMap <Integer, ShadowClass> shadowClasses;
private final ConcurrentHashMap <Integer, ShadowClass> shadowClasses;
// TODO LB: Associate class code with class loader shadow objects.
private static final ConcurrentHashMap <ShadowObject, ConcurrentHashMap <Type, byte []>> classLoaderMap;
// TODO LB: Associate class code with class loader shvm objects.
private final ConcurrentHashMap <ShadowObject, ConcurrentHashMap <Type, byte []>> classLoaderMap;
//
static {
JAVA_LANG_CLASS = new AtomicReference <> ();
__JAVA_LANG_CLASS_TYPE__ = Type.getType (Class.class);
/**
* The default constructor.
* Receive the current shvm VM context.
*/
public ShadowClassTable(final SHVMContext shvmContext)
{
shadowClasses = new ConcurrentHashMap <> (__INITIAL_SIZE__);
classLoaderMap = new ConcurrentHashMap <> (__INITIAL_SIZE__);
BOOTSTRAP_CLASSLOADER = new ShadowObject (0, null);
classLoaderMap.put (BOOTSTRAP_CLASSLOADER, new ConcurrentHashMap <> ());
}
/**
* The default constructor.
* Receive the current shadow VM context.
*/
public ShadowClassTable(final SHVMContext shvmContext){
__shvmContext = shvmContext;
}
......@@ -89,10 +83,10 @@ public final class ShadowClassTable {
/**
* Returns name of the classloader, or the default on if absent.
*
* @param classLoader ClassLoader shadow object
* @param classLoader ClassLoader shvm object
* @return ShadowObject of classloader.
*/
private static ShadowObject __safeClassLoader (final ShadowObject classLoader) {
private ShadowObject __safeClassLoader (final ShadowObject classLoader) {
return (classLoader != null) ? classLoader : BOOTSTRAP_CLASSLOADER;
}
......@@ -131,7 +125,7 @@ public final class ShadowClassTable {
// Someone else just created a class with the same class id,
// but for some reason the classes are not equal.
throw new DiSLREServerFatalException (String.format (
"different shadow classes (%s) for id (0x%x)",
"different shvm classes (%s) for id (0x%x)",
type, classId
));
}
......@@ -179,7 +173,7 @@ public final class ShadowClassTable {
final byte [] classCode = classTypeMap.get (type);
if (classCode == null || classCode.length == 0) {
//
// Lambda classes have no bytecode. Create a dummy shadow class
// Lambda classes have no bytecode. Create a dummy shvm class
// for them until we need to figure out how to get the information
// about the class (i.e. what interface it implements) to the
// Shadow VM.
......@@ -206,7 +200,7 @@ public final class ShadowClassTable {
/**
* Return shadow class for given classId or null for zero.
* Return shvm class for given classId or null for zero.
*
* @param classId
* @return ShadowClass
......
package ch.usi.dag.dislreserver.shadow;
import ch.usi.dag.dislreserver.DiSLREServerFatalException;
import ch.usi.dag.shvm.DiSLREServerFatalException;
import java.util.Formattable;
import java.util.Formatter;
......@@ -169,11 +169,11 @@ public class ShadowObject implements Formattable {
private boolean __equals (final ShadowObject other) {
//
// The equality of shadow objects should be based purely on the equality of
// The equality of shvm objects should be based purely on the equality of
// the net reference, without taking into account the special bit which
// indicates whether the object has been sent with additional data.
//
// The value of some special shadow objects can be updated lazily, so we
// The value of some special shvm objects can be updated lazily, so we
// should not really compare their values unless we can make sure that
// the comparison makes sense at all times.
//
......@@ -184,7 +184,7 @@ public class ShadowObject implements Formattable {
final void updateFrom (final ShadowObject other) {
//
// When updating value from another shadow object, the net reference
// When updating value from another shvm object, the net reference
// of this and the other object (without the special bit) must be the same.
// The other object must have the SPECIAL bit set (this is checked by the
// caller of this method).
......@@ -202,10 +202,10 @@ public class ShadowObject implements Formattable {
/**
* This method is intended to be overriden by subclasses to update shadow
* This method is intended to be overriden by subclasses to update shvm
* object's internal values. The caller of this method guarantees that the
* unique id part of the net reference of the object to update from will be
* the same as that of this shadow object. In addition, the other object
* the same as that of this shvm object. In addition, the other object
* will have the special bit of the net reference set, indicating that it
* contains additional payload specific to that object.
*
......
......@@ -4,9 +4,9 @@ import java.util.Iterator;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import ch.usi.dag.dislreserver.DiSLREServerFatalException;
import ch.usi.dag.dislreserver.Logging;
import ch.usi.dag.dislreserver.SHVMContext;
import ch.usi.dag.shvm.DiSLREServerFatalException;
import ch.usi.dag.shvm.Logging;
import ch.usi.dag.shvm.SHVMContext;
import org.objectweb.asm.Type;
import ch.usi.dag.util.logging.Logger;
......@@ -26,7 +26,7 @@ public final class ShadowObjectTable {
/**
* Default constructor.
*
* @param shvmContext The parent shadow VM context.
* @param shvmContext The parent shvm VM context.
*/
public ShadowObjectTable(final SHVMContext shvmContext){
__shvmContext = shvmContext;
......@@ -36,12 +36,12 @@ public final class ShadowObjectTable {
/**
* Register new shadow object.
* Register new shvm object.
* @param object
*/
void register (final ShadowObject object) {
if (object == null) {
__log.warn ("attempting to register a null shadow object");
__log.warn ("attempting to register a null shvm object");
return;
}
......@@ -51,7 +51,7 @@ public final class ShadowObjectTable {
final ShadowObject existing = shadowObjects.putIfAbsent (objectId, object);
if (existing != null && object.isSpecial ()) {
if (__log.traceIsLoggable ()) {
__log.trace ("updating shadow object 0x%x", objectId);
__log.trace ("updating shvm object 0x%x", objectId);
}
existing.updateFrom (object);
......@@ -72,8 +72,8 @@ public final class ShadowObjectTable {
}
//
// The corresponding shadow object was not found, so we create it.
// Only "normal" shadow objects will be generated here, not those
// The corresponding shvm object was not found, so we create it.
// Only "normal" shvm objects will be generated here, not those
// representing instances of the Class class.
//
if (!NetReferenceHelper.isClassInstance (netReference)) {
......@@ -119,7 +119,7 @@ public final class ShadowObjectTable {
__shvmContext.getShadowClassTable ().freeShadowObject (object);
}
//TODO: find a more elegant way to allow users to traverse the shadow object table
//TODO: find a more elegant way to allow users to traverse the shvm object table
public Iterator <Entry <Long, ShadowObject>> getIterator () {
return shadowObjects.entrySet ().iterator ();
}
......@@ -135,7 +135,7 @@ public final class ShadowObjectTable {
}
// TODO LB: Make this interface per-shadow-world instead of static.
// TODO LB: Make this interface per-shvm-world instead of static.
public void registerShadowThread (
final long netReference, final String name, final boolean isDaemon
......
......@@ -40,7 +40,7 @@ public final class ShadowString extends ShadowObject {
protected void _updateFrom (final ShadowObject object) {
//
// If the value of this string has not yet been initialized,
// update it from the other shadow string. The other string
// update it from the other shvm string. The other string
// is expected to have the same net reference.
//
if (__value.get () == null) {
......
......@@ -67,7 +67,7 @@ public final class ShadowThread extends ShadowObject implements Formattable {
@Override
protected void _updateFrom (final ShadowObject object) {
//
// Update the thread information from the other shadow thread.
// Update the thread information from the other shvm thread.
// Both objects are expected to have the same net reference.
//
if (object instanceof ShadowThread) {
......
package ch.usi.dag.dislreserver;
package ch.usi.dag.shvm;
import ch.usi.dag.util.logging.Logger;
......@@ -21,7 +21,7 @@ public final class Logging {
* Default prefix for top-level logs.
*/
private static final String
__NEW_PREFIX__ = "dislreserver";
__NEW_PREFIX__ = "shvm";
/**
* Register provider property alias with the logging class.
......
......@@ -101,7 +101,7 @@ CFLAGS += -I$(INCLUDE_DIR) -I$(INCLUDE_DIR)/$(JDK_TARGET)
# Source code options
#CFLAGS += -W -Wall -Wextra -Wno-unused-parameter
CFLAGS += -std=gnu99 -W -Wall -Wextra -Wno-unused-parameter
CFLAGS += -std=gnu99 -W -Wall -Wextra -Wno-unused-parameter -Wno-unused-function
# Fix-up quirks before first target
-include Makefile.quirks
......
......@@ -48,7 +48,7 @@
* rdatiprefix - Runtime Diagnostics Thread Info Prefixed printf
*/
#define common_rdatiprefix(agent_name, info, args...) \
rdoutput (agent_name " [%s, %" PRId64 "]: ", __safe_name ((info)->name), (info)->id); \
rdoutput (agent_name " [%s, %" PRId64 "]: ", __safe_name ((info)->name), (int64_t)(info)->id); \
rdoutput (args);
......
/**
* DO NOT EDIT!
*
* This file was generated using the 'generate-disl-agent-bytecode' target.
* This file was generated using the '-generate-disl-agent-bytecode' target.
*/
#include <jvmti.h>
jvmtiClassDefinition always_BypassCheck_classdef = {
.class_byte_count = 388,
.class_bytes = (unsigned char *)
"\xca\xfe\xba\xbe\x00\x00\x00\x30\x00\x12\x0a\x00\x03\x00\x0f\x07"
"\xca\xfe\xba\xbe\x00\x00\x00\x32\x00\x12\x0a\x00\x03\x00\x0f\x07"
"\x00\x10\x07\x00\x11\x01\x00\x06\x3c\x69\x6e\x69\x74\x3e\x01\x00"
"\x03\x28\x29\x56\x01\x00\x04\x43\x6f\x64\x65\x01\x00\x0f\x4c\x69"
"\x6e\x65\x4e\x75\x6d\x62\x65\x72\x54\x61\x62\x6c\x65\x01\x00\x12"
......@@ -38,7 +38,7 @@ jvmtiClassDefinition always_BypassCheck_classdef = {
jvmtiClassDefinition dynamic_BypassCheck_classdef = {
.class_byte_count = 460,
.class_bytes = (unsigned char *)
"\xca\xfe\xba\xbe\x00\x00\x00\x30\x00\x17\x0a\x00\x04\x00\x10\x0a"
"\xca\xfe\xba\xbe\x00\x00\x00\x32\x00\x17\x0a\x00\x04\x00\x10\x0a"
"\x00\x11\x00\x12\x07\x00\x13\x07\x00\x14\x01\x00\x06\x3c\x69\x6e"
"\x69\x74\x3e\x01\x00\x03\x28\x29\x56\x01\x00\x04\x43\x6f\x64\x65"
"\x01\x00\x0f\x4c\x69\x6e\x65\x4e\x75\x6d\x62\x65\x72\x54\x61\x62"
......@@ -72,7 +72,7 @@ jvmtiClassDefinition dynamic_BypassCheck_classdef = {
jvmtiClassDefinition never_BypassCheck_classdef = {
.class_byte_count = 388,
.class_bytes = (unsigned char *)
"\xca\xfe\xba\xbe\x00\x00\x00\x30\x00\x12\x0a\x00\x03\x00\x0f\x07"
"\xca\xfe\xba\xbe\x00\x00\x00\x32\x00\x12\x0a\x00\x03\x00\x0f\x07"
"\x00\x10\x07\x00\x11\x01\x00\x06\x3c\x69\x6e\x69\x74\x3e\x01\x00"
"\x03\x28\x29\x56\x01\x00\x04\x43\x6f\x64\x65\x01\x00\x0f\x4c\x69"
"\x6e\x65\x4e\x75\x6d\x62\x65\x72\x54\x61\x62\x6c\x65\x01\x00\x12"
......
/*
* bytecode.h
*
* This file is a header to bytecode.c file, that is auto generated during
* the build phase.
*/
#ifndef _BYTECODE_H_
#define _BYTECODE_H_
#define _BYTECODE_H_
#include <jvmti.h>
/**
/*
* Name of the class used for bypass checks.
*/
#define BPC_CLASS_NAME "ch/usi/dag/disl/dynamicbypass/BypassCheck"
#define BPC_CLASS_NAME "ch/usi/dag/disl/dynamicbypass/BypassCheck"
/**
/*
* Externs for various implementations of the BypassCheck class.
*/
extern jvmtiClassDefinition always_BypassCheck_classdef;
......
......@@ -10,15 +10,27 @@ typedef const uint8_t * utf8_t;
//
class_t class_alloc (const uint8_t * class_bytes, size_t byte_count);
void class_free (class_t java_class);
class_t
class_alloc(const uint8_t * class_bytes, size_t byte_count);
char * class_name (class_t java_class);
char * class_super_class_name (class_t java_class);
bool class_has_super_class (class_t java_class);
void
class_free(class_t java_class);
int class_interface_count (class_t java_class);
char * class_interface_name (class_t java_class, int index);
char *
class_name(class_t java_class);
char *
class_super_class_name(class_t java_class);
bool
class_has_super_class(class_t java_class);
#endif /* _CLASSPARSER_H */
int
class_interface_count(class_t java_class);
char *
class_interface_name(class_t java_class, int index);
#endif /* _CLASSPARSER_H */
......@@ -4,7 +4,7 @@
* It's purpose is to manage the connections
*/
#ifndef _CONNECTION_H_
#define _CONNECTION_H_
#define _CONNECTION_H_
#include <sys/types.h>
......@@ -29,35 +29,46 @@
//
struct connection {
/** File descriptor of the connection socket. */
/* File descriptor of the connection socket. */
int sockfd;
/** Link in the connection pool list. */
/* Link in the connection pool list. */
struct list cp_link;
#ifdef DEBUG
/** Number of bytes sent over the connection. */
/* Number of bytes sent over the connection. */
uint64_t sent_bytes;
/** Number of bytes received over the connection. */
/* Number of bytes received over the connection. */
uint64_t recv_bytes;
#endif /* DEBUG */
};
struct connection * connection_open (struct addrinfo * addr);
void connection_close (struct connection * connection);
struct connection * connection_open(struct addrinfo * addr);
void connection_close(struct connection * connection);
ssize_t connection_send_full (struct connection * connection, const void * buf, const size_t len);
ssize_t connection_recv_full (struct connection * connection, void * buf, const size_t len);
ssize_t connection_recv (struct connection * connection, void * buf, const size_t len);
ssize_t
connection_send_full(
struct connection * connection, const void * buf, size_t len);
ssize_t
connection_recv_full(struct connection * connection, void * buf, size_t len);
ssize_t
connection_recv(struct connection * connection, void * buf, size_t len);
#ifndef MINGW
#include <sys/uio.h>
ssize_t connection_send_iov_full (struct connection * connection, struct iovec * iovs, int iov_count);
ssize_t connection_recv_iov_full (struct connection * connection, struct iovec * iovs, int iov_count);
ssize_t
connection_send_iov_full(
struct connection * connection, struct iovec * iovs, int iov_count);
ssize_t
connection_recv_iov_full(
struct connection * connection, struct iovec * iovs, int iov_count);
#endif
......
......@@ -5,138 +5,148 @@
#include <stdio.h>
/**
/*
* Initializes the given connection pool. New connections created by the
* pool will connect to the given endpoint.
*/
void
connection_pool_init (struct connection_pool * cp, struct addrinfo * endpoint) {
assert (cp != NULL);
assert (endpoint != NULL);
connection_pool_init(struct connection_pool * cp, struct addrinfo * endpoint)
{
assert(cp != NULL);
assert(endpoint != NULL);
cp->connections_count = 0;
list_init (&cp->free_connections);
list_init (&cp->busy_connections);
list_init(&cp->free_connections);
list_init(&cp->busy_connections);
cp->endpoint = endpoint;
cp->after_open_hook = NULL;
cp->before_close_hook = NULL;
}
/**
/*
* Sets a callback to be invoked after a new connection has been opened.
* The connection pool may open new connections when there is no unused
* connection available.
*/
void
connection_pool_set_after_open_hook (struct connection_pool * cp, connection_hook_fn after_open_fn) {
assert (cp != NULL);
connection_pool_set_after_open_hook(
struct connection_pool * cp, connection_hook_fn after_open_fn
)
{
assert(cp != NULL);
cp->after_open_hook = after_open_fn;
}
/**
/*
* Sets a callback to be invoked before closing a connection.
* The connection pool may close connections when there are too many
* connections open, or when the connection pool itself is being destroyed.
*/
void
connection_pool_set_before_close_hook (struct connection_pool * cp, connection_hook_fn before_close_fn) {
assert (cp != NULL);
connection_pool_set_before_close_hook(
struct connection_pool * cp, connection_hook_fn before_close_fn
)
{
assert(cp != NULL);
cp->before_close_hook = before_close_fn;
}
/**
/*
* Acquires a connection from a pool of available connections. Creates a new
* connection if none is currently available. This operation is thread-unsafe.
*/
struct connection *
connection_pool_get_connection (struct connection_pool * cp) {
assert (cp != NULL);
connection_pool_get_connection(struct connection_pool * cp)
{
assert(cp != NULL);
ldebug ("getting connection for %s: ", cp->endpoint->ai_canonname);
ldebug("getting connection for %s: ", cp->endpoint->ai_canonname);
//
// Grab the first available connection and return. If there is no connection
// available, create a new one and add it to the busy connection list.
// Grab the first available connection and return. If there is no
// connection available, create a new one and add it to the busy
// connection list.
//
if (!list_is_empty (&cp->free_connections)) {
debug ("reusing a connection [%d in total]\n", cp->connections_count);
struct list * item = list_remove_after (&cp->free_connections);
list_insert_after (item, &cp->busy_connections);
return list_item (item, struct connection, cp_link);
if (!list_is_empty(&cp->free_connections)) {
debug("reusing a connection [%d in total]\n",
cp->connections_count);
struct list * item = list_remove_after(&cp->free_connections);
list_insert_after(item, &cp->busy_connections);
return (list_item(item, struct connection, cp_link));
} else {
struct connection * connection = connection_open (cp->endpoint);
struct connection * connection = connection_open(cp->endpoint);
if (cp->after_open_hook != NULL) {
cp->after_open_hook (connection);
cp->after_open_hook(connection);
}
list_insert_after (&connection->cp_link, &cp->busy_connections);
list_insert_after(&connection->cp_link, &cp->busy_connections);
cp->connections_count++;
debug ("created new connection [%d in total]\n", cp->connections_count);
return connection;
debug("created new connection [%d in total]\n",
cp->connections_count);
return (connection);
}
}
/**
/*
* Releases the given connection and puts it back to the pool of available
* connections. This operation is thread-unsafe.
*/
void
connection_pool_put_connection (
connection_pool_put_connection(
struct connection_pool * cp, struct connection * connection
) {
assert (cp != NULL);
assert (connection != NULL);
)
{
assert(cp != NULL);
assert(connection != NULL);
//
// Move the connection from the list of busy connections to
// the list of available connections.
//
struct list * item = list_remove (&connection->cp_link);
list_insert_after (item, &cp->free_connections);
struct list * item = list_remove(&connection->cp_link);
list_insert_after(item, &cp->free_connections);
}
//
static void
__connection_destructor (struct list * item, void * data) {
struct connection * connection = list_item (item, struct connection, cp_link);
__connection_destructor(struct list * item, void * data)
{
struct connection * connection = list_item(item, struct connection,
cp_link);
struct connection_pool * cp = (struct connection_pool *) data;
if (cp->before_close_hook != NULL) {
cp->before_close_hook (connection);
cp->before_close_hook(connection);
}
connection_close (connection);
connection_close(connection);
cp->connections_count--;
}
/**
/*
* Closes all connections in the given connection pool. The connection pool
* may be reused to open new connections to the host it was initialized for.
*/
void
connection_pool_close (struct connection_pool * cp) {
assert (cp != NULL);
ldebug (
"closing pool for %s: max connections %d\n",
cp->endpoint->ai_canonname, cp->connections_count
);
list_destroy (&cp->free_connections, __connection_destructor, (void *) cp);
if (!list_is_empty (&cp->busy_connections)) {
warn ("closing %d active connections", cp->connections_count);
list_destroy (&cp->busy_connections, __connection_destructor, (void *) cp);
connection_pool_close(struct connection_pool * cp)
{
assert(cp != NULL);
ldebug("closing pool for %s: max connections %d\n",
cp->endpoint->ai_canonname, cp->connections_count);
list_destroy(
&cp->free_connections, __connection_destructor, (void *) cp);
if (!list_is_empty(&cp->busy_connections)) {
warn("closing %d active connections", cp->connections_count);
list_destroy(
&cp->busy_connections, __connection_destructor,
(void *) cp);
}
}
#ifndef _CONNPOOL_H_
#define _CONNPOOL_H_
#ifndef _CONNPOOL_H_
#define _CONNPOOL_H_
#include <sys/types.h>
......@@ -14,12 +14,10 @@
#include "list.h"
#include "connection.h"
/**
/*
* Callback function type for events on the connection pool.
*/
typedef void (* connection_hook_fn) (struct connection * connection);
typedef void (* connection_hook_fn)(struct connection * connection);
struct connection_pool {
int connections_count;
......@@ -31,14 +29,30 @@ struct connection_pool {
connection_hook_fn before_close_hook;
};
void
connection_pool_init(struct connection_pool * cp, struct addrinfo * endpoint);
void
connection_pool_close(struct connection_pool * cp);
void
connection_pool_set_after_open_hook(
struct connection_pool * cp, connection_hook_fn after_open_fn
);
void
connection_pool_set_before_close_hook(
struct connection_pool * cp, connection_hook_fn before_close_fn
);
void connection_pool_init (struct connection_pool * cp, struct addrinfo * endpoint);
void connection_pool_close (struct connection_pool * cp);
void connection_pool_set_after_open_hook (struct connection_pool * cp, connection_hook_fn after_open_fn);
void connection_pool_set_before_close_hook (struct connection_pool * cp, connection_hook_fn before_close_fn);
struct connection *
connection_pool_get_connection(struct connection_pool * cp);
struct connection * connection_pool_get_connection (struct connection_pool * cp);
void connection_pool_put_connection (struct connection_pool * cp, struct connection * connection);
void
connection_pool_put_connection(
struct connection_pool * cp, struct connection * connection
);
#endif /* _CONNPOOL_H_ */
This diff is collapsed.
/**
/*
* This file is part of src_shvm_agent.
* Contains the agent settings, that can be extracted from main agent file.
*
* Created by Vít Kabele on 2019-03-10.
*/
#ifndef SRC_SHVM_AGENT_DISL_H
#define SRC_SHVM_AGENT_DISL_H
#ifndef SRC_SHVM_AGENT_DISL_H
#define SRC_SHVM_AGENT_DISL_H
#include <jvmti.h>
#include "codeflags.h"
#include "../common.h"
#include "../config.h"
/**
/*
* Flag indicating that the VM has been started, which
* allows calling any JNI function.
*/
static volatile bool jvm_is_started;
/**
/*
* Flag indicating that the VM has been initialized,
* which allows calling any JNI or JVMTI function.
*/
static volatile bool jvm_is_initialized;
/**
/*
* Flags representing code options, derived from the values generated from Java.
*/
enum code_flags {
CF_CREATE_BYPASS = ch_usi_dag_disl_DiSL_CodeOption_Flag_CREATE_BYPASS,
CF_DYNAMIC_BYPASS = ch_usi_dag_disl_DiSL_CodeOption_Flag_DYNAMIC_BYPASS,
CF_SPLIT_METHODS = ch_usi_dag_disl_DiSL_CodeOption_Flag_SPLIT_METHODS,
CF_CATCH_EXCEPTIONS = ch_usi_dag_disl_DiSL_CodeOption_Flag_CATCH_EXCEPTIONS,
CF_CREATE_BYPASS = ch_usi_dag_disl_DiSL_CodeOption_Flag_CREATE_BYPASS,
CF_DYNAMIC_BYPASS = ch_usi_dag_disl_DiSL_CodeOption_Flag_DYNAMIC_BYPASS,
CF_SPLIT_METHODS = ch_usi_dag_disl_DiSL_CodeOption_Flag_SPLIT_METHODS,
CF_CATCH_EXCEPTIONS = ch_usi_dag_disl_DiSL_CodeOption_Flag_CATCH_EXCEPTIONS,
};
/**
/*
* Code option flags that control the instrumentation.
*/
volatile jint agent_code_flags;
......@@ -49,31 +46,31 @@ void
disl_finish();
jint
calc_code_flags (const struct config * config, bool jvm_is_booting);
calc_code_flags(const struct config * config, bool jvm_is_booting);
// ****************************************************************************
// JVMTI EVENT: VM INIT
// ****************************************************************************
void JNICALL
disl_jvmti_callback_vm_init (jvmtiEnv * jvmti, JNIEnv * jni, jthread thread);
disl_jvmti_callback_vm_init(jvmtiEnv * jvmti, JNIEnv * jni, jthread thread);
// ****************************************************************************
// JVMTI EVENT: VM START
// ****************************************************************************
void JNICALL
disl_jvmti_callback_vm_start (jvmtiEnv * jvmti, JNIEnv * jni);
disl_jvmti_callback_vm_start(jvmtiEnv * jvmti, JNIEnv * jni);
// ****************************************************************************
// JVMTI EVENT: VM DEATH
// ****************************************************************************
void JNICALL
disl_jvmti_callback_vm_death (jvmtiEnv * jvmti, JNIEnv * jni);
disl_jvmti_callback_vm_death(jvmtiEnv * jvmti, JNIEnv * jni);
// ****************************************************************************
// JVMTI EVENT: CLASS FILE LOAD
// ****************************************************************************
void JNICALL
disl_jvmti_callback_class_file_load (
disl_jvmti_callback_class_file_load(
jvmtiEnv * jvmti, JNIEnv * jni,
jclass class_being_redefined, jobject classloader,
const char * class_name, jobject protection_domain,
......@@ -81,4 +78,4 @@ disl_jvmti_callback_class_file_load (
jint * new_class_byte_count, unsigned char ** new_class_bytes
);
#endif //SRC_SHVM_AGENT_DISL_H
#endif // SRC_SHVM_AGENT_DISL_H
......@@ -16,91 +16,102 @@
#ifdef MINGW
static inline ssize_t
__send (struct connection * conn, void * header, const size_t header_size, void * body, const size_t body_size) {
ssize_t sent = connection_send_full (conn, header, header_size);
sent += connection_send_full (conn, body, body_size);
return sent;
__send(
struct connection * conn, void * header, const size_t header_size,
void * body, const size_t body_size
)
{
ssize_t sent = connection_send_full(conn, header, header_size);
sent += connection_send_full(conn, body, body_size);
return (sent);
}
#else
static inline ssize_t
__send (struct connection * conn, void * header, const size_t header_size, void * body, const size_t body_size) {
struct iovec iovs [] = {
{ .iov_base = header, .iov_len = header_size },
{ .iov_base = body, .iov_len = body_size },
__send(
struct connection * conn, void * header, const size_t header_size,
void * body, const size_t body_size
)
{
struct iovec iovs[] = {
{.iov_base = header, .iov_len = header_size},
{.iov_base = body, .iov_len = body_size},
};
return connection_send_iov_full (conn, &iovs [0], sizeof_array (iovs));
return (connection_send_iov_full(conn, &iovs[0], sizeof_array(iovs)));
}
#endif /* !MINGW */
/**
/*
* Sends the given message to the remote instrumentation server
* via the given connection. Returns the number of bytes sent.
*/
ssize_t
message_send (struct connection * conn, void * message, const size_t message_size) {
assert (conn != NULL);
assert (message != NULL);
message_send(
struct connection * conn, void * message, const size_t message_size
)
{
assert(conn != NULL);
assert(message != NULL);
ldebug ("sending message: %lu bytes", message_size);
ldebug("sending message: %lu bytes", message_size);
//
uint32_t message_size_data = htonl (message_size);
uint32_t message_size_data = htonl(message_size);
size_t header_size = sizeof (message_size_data);
ssize_t sent = __send (conn, &message_size_data, header_size, message, message_size);
assert (sent == (ssize_t) (header_size + message_size));
ssize_t sent = __send(
conn, &message_size_data, header_size, message, message_size);
assert(sent == (ssize_t) (header_size+message_size));
//
debug (", sent %ld bytes\n", sent);
return sent;
debug(", sent %ld bytes\n", sent);
return (sent);
}
static inline uint8_t *
__alloc_buffer (size_t len) {
__alloc_buffer(size_t len)
{
//
// Allocate a buffer with an extra (zeroed) byte, but only if the
// requested buffer length is greater than zero. Return NULL otherwise.
//
if (len == 0) {
return NULL;
return (NULL);
}
//
uint8_t * buf = (uint8_t *) malloc (len + 1);
check_error (buf == NULL, "failed to allocate buffer");
uint8_t * buf = (uint8_t *) malloc(len+1);
check_error(buf == NULL, "failed to allocate buffer");
buf [len] = '\0';
return buf;
buf[len] = '\0';
return (buf);
}
/**
/*