Commit c68f274e authored by Lubomir Bulej's avatar Lubomir Bulej

Merge branch 'shvm-flat' into 'devel'

Shvm flat

See merge request !5
parents b8d6f9dd c740918b
Pipeline #4601 passed with stages
in 3 minutes and 46 seconds
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="output/build/disl" path="src-disl"/>
<classpathentry kind="src" output="output/build/shvm" path="src-shvm"/>
<classpathentry kind="src" output="output/build/util" path="src-util"/>
<classpathentry kind="src" output="output/build/test" path="src-test"/>
<classpathentry kind="src" output="output/build/shvm-dispatch" path="src-shvm-dispatch"/>
......@@ -25,6 +24,24 @@
<classpathentry kind="src" path="disl/src/src-annotation"/>
<classpathentry kind="src" path="disl/src/src-context"/>
<classpathentry kind="src" path="disl/src-test"/>
<classpathentry kind="src" path="shvm/src/src-dislreserver"/>
<classpathentry kind="src" path="shvm/src/src-msg-analyze"/>
<classpathentry kind="src" path="shvm/src/src-msg-close"/>
<classpathentry kind="src" path="shvm/src/src-msg-classinfo"/>
<classpathentry kind="src" path="shvm/src/src-msg-newclass"/>
<classpathentry kind="src" path="shvm/src/src-msg-objfree"/>
<classpathentry kind="src" path="shvm/src/src-msg-reganalysis"/>
<classpathentry kind="src" path="shvm/src/src-msg-instr"/>
<classpathentry kind="src" path="shvm/src/src-msg-stringinfo"/>
<classpathentry kind="src" path="shvm/src/src-msg-threadend"/>
<classpathentry kind="src" path="shvm/src/src-msg-threadinfo"/>
<classpathentry kind="src" path="shvm/src/src-msg-analyze-mtdispatch"/>
<classpathentry kind="src" path="shvm/src/src-remoteanalysis"/>
<classpathentry kind="src" path="shvm/src/src-reqdispatch"/>
<classpathentry kind="src" path="shvm/src/src-shadow"/>
<classpathentry kind="src" path="shvm/src/src-util"/>
<classpathentry kind="src" path="shvm/src/src-server-api"/>
<classpathentry kind="src" path="shvm/src-test"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="output/lib/disl-bypass.jar"/>
<classpathentry kind="lib" path="lib/disl/log4j.jar" sourcepath="lib/devel/log4j-source.jar"/>
......
# Backup files
*~
# Generated dependency files
src-disl-agent/*.d
src-disl-agent/linux-*
src-disl-agent/windows-*
*.d
# Compiled shared libraries
*.so
......@@ -17,12 +18,15 @@ examples/**/*.jar
# Logs
*.log
# Output directories
src-disl-agent/linux-*
src-disl-agent/windows-*
# Anything in the output
output/*
# Libraries
# Runtime libraries
lib/*/*.jar
# Fallout from method uid generator
methodid.txt
......@@ -6,17 +6,17 @@ cache: &cache
key: "${CI_COMMIT_REF_SLUG}"
# Cache deps and compiled classes
paths:
- 'output/'
- 'lib/'
- 'src-disl-agent/linux-x86_64' # Specific architecture of used container
- 'output/'
- 'lib/'
- 'src-disl-agent/linux-x86_64' # Specific architecture of used container
# Adjust modification date to prevent recompiling sources in different stages.
before_script:
- find . -exec touch -t 200001010000 {} \;
- find . -exec touch -t 200001010000 {} \;
stages:
- build
- test
- build
- test
# Jobs definitions
# The YAML Anchors are used because of Gitlab Issue#2838
......@@ -29,13 +29,29 @@ build:
policy:
push
script:
- ant build
- ant build
# Run tests
test:
test compound:
stage: test
cache:
<<: *cache
policy: pull
script:
- ant test
- ant test-compound
test disl:
stage: test
cache:
<<: *cache
policy: pull
script:
- ant test-disl
test shvm:
stage: test
cache:
<<: *cache
policy: pull
script:
- ant test-shvm
......@@ -18,7 +18,7 @@ src.examples=examples
disl.bypass.lib=disl-bypass.jar
disl.agent.lib.base=dislagent
shvm.lib=dislre-server.jar
shvm.dispatch.lib=dislre-dispatch.jar
shvm.agent.lib.base=dislreagent
......
......@@ -278,7 +278,7 @@
</path>
<path id="shvm.classpath">
<pathelement location="${build.shvm}"/>
<pathelement location="${src.shvm.prefix}/${build.shvm}"/>
<pathelement location="${build.shvm.dispatch}"/>
</path>
</target>
......@@ -633,28 +633,13 @@
<target name="compile-shvm" depends="compile-util,compile-shvm-dispatch">
<mkdir dir="${build.shvm}"/>
<javac destdir="${build.shvm}" srcdir="${src.shvm}" debug="true">
<classpath refid="util.classpath"/>
<classpath refid="asm.classpath"/>
</javac>
<ant antfile="${src.shvm.prefix}/build.xml" target="compile" usenativebasedir="true"/>
</target>
<target name="build-shvm" depends="compile-shvm,build-shvm-dispatch">
<local name="shvm.server.class"/>
<find-class property="shvm.server.class" dir="${build.shvm}" name="DiSLREServer"/>
<jar destfile="${out.lib}/${shvm.lib}">
<manifest>
<attribute name="Class-Path" value="${asm.libs}"/>
<attribute name="Main-Class" value="${shvm.server.class}"/>
<attribute name="DiSL-Version" value="${disl.version}"/>
</manifest>
<fileset dir="${build.util}"/>
<fileset dir="${build.shvm}"/>
</jar>
<ant antfile="${src.shvm.prefix}/build.xml" target="build" usenativebasedir="true"/>
<copy file="${src.shvm.prefix}/${out.lib}/${shvm.lib}" tofile="${out.lib}/${shvm.lib}" />
</target>
<!-- Shadow VM agent -->
......@@ -786,12 +771,22 @@
</sequential>
</macrodef>
<!-- Run nested instrumentation library tests -->
<target name="disl-test">
<!-- Run the instrumentation library unit tests -->
<target name="test-disl">
<ant antfile="${src.disl.prefix}/build.xml" target="test" usenativebasedir="true"/>
</target>
<target name="test" depends="build,build-test,disl-test" description="Runs all tests or a selected (-Dtest.name=...) test suite.">
<!-- Run the shadow VM unit tests -->
<target name="test-shvm">
<ant antfile="${src.shvm.prefix}/build.xml" target="test" usenativebasedir="true" />
</target>
<!-- Run all tests -->
<target name="test" depends="test-disl,test-shvm,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.">
<!--
If test.name is set to a name of a test suite, only include the test suite
in the batch of tests to be run, otherwise include all tests and suites.
......@@ -830,7 +825,7 @@
<pathelement location="${build.util}"/>
<pathelement location="${src.disl-server.prefix}/${build.disl-server}" />
<pathelement location="${src.disl.prefix}/${build.disl}"/>
<pathelement location="${build.shvm}"/>
<pathelement location="${src.shvm.prefix}/${build.shvm}" />
</classpath>
<!-- pass properties starting with "disl.", "dislserver.", and "dislreserver." to the tests -->
......@@ -1066,16 +1061,13 @@
<ant dir="${src.examples}" target="clean"/>
</target>
<target name="clean-disl">
<ant dir="${src.disl.prefix}" target="clean" />
</target>
<target name="clean-disl-server">
<ant dir="${src.disl-server.prefix}" target="clean" />
</target>
<target name="clean" description="Removes all files produced during the build.">
<ant dir="${src.shvm.prefix}" target="clean" />
<ant dir="${src.disl-server.prefix}" target="clean" />
<ant dir="${src.disl.prefix}" target="clean" />
<target name="clean" depends="clean-disl, clean-disl-server" description="Removes all files produced during the build.">
<exec executable="make" dir="${src.disl.agent}">
<arg value="cleanall"/>
</exec>
......
......@@ -18,8 +18,10 @@ build.ivy.file = dependencies.xml
src.bin=bin
src.disl.prefix=disl
src.disl-server.prefix=disl-server
src.shvm.prefix=shvm
disl.lib=disl-server.jar
shvm.lib=dislre-server.jar
# Base output directory
out.dir=output
......
# Shadow VM server
# Build properties related to the SHVM package
src.shvm.test=src-test
build.shvm.test=${build.dir}/test
<project name="disl-server" default="build" basedir=".">
<!--
Import required property files.
-->
<property file="../common.properties"/>
<property file="build.properties" />
<property file="../disl.version.properties" />
<!--
Initialize the build directory
-->
<target name="init">
<mkdir dir="${build.shvm}" />
<mkdir dir="${build.shvm.test}" />
</target>
<!--
Dependency class paths
-->
<path id="asm.classpath">
<fileset dir="../${lib.disl.dir}" includes="asm*.jar" id="asm.fileset"/>
</path>
<path id="util.classpath">
<pathelement location="../${build.util}"/>
</path>
<path id="junit.classpath">
<fileset dir="../${lib.test.dir}" includes="*.jar"/>
</path>
<path id="protobuf.classpath">
<fileset dir="../${lib.disl.dir}" includes="protobuf*.jar"/>
</path>
<!--
Refer to the parent targets
-->
<target name="compile-util">
<ant antfile="../build.xml" target="compile-util" usenativebasedir="true" />
</target>
<target name="compile-shvm-dispatch">
<ant antfile="../build.xml" target="compile-shvm-dispatch" usenativebasedir="true" />
</target>
<target name="build-shvm-dispatch">
<ant antfile="../build.xml" target="build-shvm-dispatch" usenativebasedir="true" />
</target>
<!-- SHVM Server -->
<target name="compile" depends="compile-util,compile-shvm-dispatch,init">
<javac destdir="${build.shvm}" debug="true">
<src path="src/src-dislreserver" />
<src path="src/src-msg-analyze" />
<src path="src/src-msg-analyze-mtdispatch" />
<src path="src/src-msg-classinfo" />
<src path="src/src-msg-close" />
<src path="src/src-msg-instr" />
<src path="src/src-msg-newclass" />
<src path="src/src-msg-objfree" />
<src path="src/src-msg-reganalysis" />
<src path="src/src-msg-stringinfo" />
<src path="src/src-msg-threadend" />
<src path="src/src-msg-threadinfo" />
<src path="src/src-remoteanalysis" />
<src path="src/src-reqdispatch" />
<src path="src/src-server-api" />
<src path="src/src-shadow" />
<src path="src/src-util" />
<classpath>
<path path="../${src.shvm.prefix}/${build.shvm}" />
<path refid="util.classpath"/>
<path refid="asm.classpath" />
<path refid="protobuf.classpath"/>
</classpath>
</javac>
</target>
<!-- Get ASM libs from ASM class path. -->
<pathconvert pathsep=" " property="asm.libs" refid="asm.classpath">
<mapper type="flatten"/>
</pathconvert>
<!-- Get ProtoBuf Java libs from ProtoBuf class path. -->
<pathconvert pathsep=" " property="protobuf.libs" refid="protobuf.classpath">
<mapper type="flatten"/>
</pathconvert>
<target name="build" depends="compile, build-shvm-dispatch">
<jar destfile="${out.lib}/${shvm.lib}">
<manifest>
<attribute name="Class-Path" value="${asm.libs} ${protobuf.libs}"/>
<attribute name="Main-Class" value="ch.usi.dag.dislreserver.DiSLREServer"/>
<attribute name="DiSL-Version" value="${disl.version}"/>
</manifest>
<service type="javax.annotation.processing.Processor" provider="ch.usi.dag.disl.DislClassFinder"/>
<fileset dir="${build.shvm}" />
<fileset dir="../${build.util}"/>
</jar>
</target>
<target name="compile-tests" depends="compile">
<javac destdir="${build.shvm.test}" debug="true" srcdir="${src.shvm.test}" includeantruntime="false">
<classpath>
<path refid="util.classpath"/>
<path refid="asm.classpath"/>
<path refid="junit.classpath"/>
<path path="${build.shvm}"/>
</classpath>
</javac>
</target>
<target name="test" depends="compile-tests" description="Run all unit tests">
<echo>Running SHVM instrumentation library tests...</echo>
<junit haltonfailure="yes" haltonerror="yes" failureproperty="junit.failure">
<formatter type="brief" usefile="false"/>
<classpath>
<path refid="asm.classpath"/>
<path refid="junit.classpath"/>
<path path="${build.shvm.test}"/>
<path path="../${build.util}"/>
<path path="${build.shvm}"/>
</classpath>
<batchtest fork="yes">
<fileset dir="${src.shvm.test}">
<include name="**/*Test.java"/>
</fileset>
</batchtest>
</junit>
</target>
<!--
Clean the build directory
-->
<target name="clean">
<delete dir="output" />
</target>
</project>
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,6 +12,9 @@ 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;
......@@ -155,7 +158,7 @@ abstract class ShadowClassTestBase {
private void __assertFieldArraysEqual (
final Field [] fields, final FieldInfo [] shadowFields
final Field [] fields, final FieldInfo[] shadowFields
) {
Assert.assertEquals (fields.length, shadowFields.length);
......
package ch.usi.dag.dislreserver;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.StandardSocketOptions;
import java.nio.channels.ClosedByInterruptException;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import ch.usi.dag.dislreserver.reqdispatch.RequestDispatcher;
import ch.usi.dag.dislreserver.util.Logging;
import ch.usi.dag.util.logging.Logger;
......@@ -29,6 +18,7 @@ public abstract class DiSLREServer {
//
private static final String PROP_DEBUG = "debug";
@Deprecated
private static final boolean debug = Boolean.getBoolean(PROP_DEBUG);
private static final String PROP_PORT = "dislreserver.port";
......@@ -55,7 +45,9 @@ public abstract class DiSLREServer {
__log.debug ("server started");
__serverStarted ();
run (socket);
ISHVM server = new SHVM (socket, __log, debug);
server.run ();
__log.debug ("server shutting down");
__closeSocket (socket);
......@@ -65,87 +57,7 @@ public abstract class DiSLREServer {
}
private static void run (final ServerSocketChannel socket) {
try {
final SocketChannel clientSocket = socket.accept ();
__log.debug (
"connection from %s", clientSocket.getRemoteAddress ()
);
processRequests (clientSocket.socket ());
clientSocket.close ();
} catch (final ClosedByInterruptException cbie) {
//
// The server was interrupted, we are shutting down.
//
} catch (final IOException ioe) {
//
// Communication error -- just log a message here.
//
__log.error ("error accepting a connection: %s", ioe.getMessage ());
}
}
private static void processRequests (final Socket sock) {
try {
final DataInputStream is = new DataInputStream (
new BufferedInputStream (sock.getInputStream ()));
final DataOutputStream os = new DataOutputStream (
new BufferedOutputStream (sock.getOutputStream ()));
REQUEST_LOOP: while (true) {
final byte requestNo = is.readByte ();
if (RequestDispatcher.dispatch (requestNo, is, os, debug)) {
break REQUEST_LOOP;
}
}
} catch (final Exception e) {
__logError (e);
}
}
private static void __logError (final Throwable throwable) {
if (throwable instanceof DiSLREServerException) {
__logNestedErrors (throwable);
if (__log.debugIsLoggable ()) {
__log.debug (__getFullMessage (throwable));
}
} else {
// some other exception
__log.error ("fatal error: %s", __getFullMessage (throwable));
}
}
private static void __logNestedErrors (final Throwable throwable) {
String prefix = "server error: ";
Throwable current = throwable;
do {
final String message = throwable.getMessage ();
if (message != null) {
__log.error ("%s%s", prefix, message);
}
prefix = "\t";
current = throwable.getCause ();
} while (current != null);
}
private static String __getFullMessage (final Throwable t) {
final StringWriter result = new StringWriter ();
t.printStackTrace (new PrintWriter (result));
return result.toString ();
}
//
......@@ -197,12 +109,24 @@ public abstract class DiSLREServer {
}
/**
* Returns reference to the file named by the property provided
* in parameter name.
*
* @param name Name of the property
* @return file reference or null while non-existing property
*/
private static File __getFileProperty (final String name) {
final String value = System.getProperty (name, "").trim ();
return value.isEmpty () ? null : new File (value);
}
/**
* Close the socket
*
* @param socket
*/
private static void __closeSocket (final Closeable socket) {
try {
socket.close ();
......
/**
* Logging methods extracted from DiSLREServer class
*
* Author: Vit Kabele <vit@kabele.me>
* Created on the 21/02/2019
*/
package ch.usi.dag.dislreserver;
import ch.usi.dag.util.logging.Logger;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* Logging methods extracted from DiSLREServer class
*/
abstract class Log {
private static String __getFullMessage (final Throwable t) {
final StringWriter result = new StringWriter ();
t.printStackTrace (new PrintWriter (result));
return result.toString ();
}
private static void __logNestedErrors (final Throwable throwable, final Logger __log) {
String prefix = "server error: ";
Throwable current = throwable;
do {
final String message = throwable.getMessage ();
if (message != null) {
__log.error ("%s%s", prefix, message);
}
prefix = "\t";
current = throwable.getCause ();
} while (current != null);
}
static void __logError (final Throwable throwable, final Logger __log) {
if (throwable instanceof DiSLREServerException) {
__logNestedErrors (throwable, __log);
if (__log.debugIsLoggable ()) {
__log.debug (Log.__getFullMessage (throwable));
}
} else {
// some other exception
__log.error ("fatal error: %s", Log.__getFullMessage (throwable));
}
}
}
/**
* ISHVM implementation
*
* Author: Vit Kabele <vit@kabele.me>
* Created on the 21/02/2019
*/
package ch.usi.dag.dislreserver;
import java.io.*;
import java.net.Socket;
import java.nio.channels.ClosedByInterruptException;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import ch.usi.dag.util.logging.Logger;
/**
* Implementation of ISHVM.
*
* This class should represent the one re-usable class that will represent
* i.e. one analysis session. All the needed data including reflective information
* should be available in its instance.
*/
public class SHVM implements ISHVM {
/**
* Socket for communication with client
*/
private final ServerSocketChannel __socket;
/**
* Logger instance
*/
private final Logger __log;
/**
* Debug flag
*/
@Deprecated
private final boolean __debug;
/**
* Request dispatcher
*/
private final RequestDispatcher __requestDispatcher;
/**
* Shadow VM context. It's used in the request dispatcher,
* but since the name is {@link SHVMContext} it does make
* a sense to initialize the instance here.
*/