Commit 99f777cf authored by Lukáš Marek's avatar Lukáš Marek

Merged changes from stable branch disl_1.0.x -r 582:587

Fixed build
parent e2dad50e
The DiSL language is hosted in Java using annotations, therefore, no special compiler is required.
A convenient way to specify an instrumentation and to pass it to the DiSL framework is to pack the instrumentation classes with a manifest file into one jar.
The DiSL framework will load the jar, parse the instrumentation specification, and instrument all classes used by an application at load-time.
DiSL
====
The examples of simple instrumentation are in src-test directory.
The test can be invoked using runTest.sh script in the root directory.
For user defined instrumentation, it is recommended to mimic the start and build script as they are provided for the tests.
We are working on better setup scripts to ease the setup effort for developer.
DiSL is inspired by AOP, but in contrast to mainstream AOP languages, it features
an open join point model where any region of bytecodes can be selected as a join
point (i.e., code location to be instrumented). DiSL reconciles high-level
language constructs resulting in concise instrumentations, high expressiveness,
and efficiency of the inserted instrumentation code. Thanks to the
pointcut/advice model adopted by DiSL, instrumentations are similarly compact as
aspects written in AspectJ. However, in contrast to AspectJ, DiSL does not
restrict the code locations that can be instrumented, and the code generated by
DiSL avoids expensive operations (such as object allocations that are not visible
to the programmer). Furthermore, DiSL supports instrumentations with complete
bytecode coverage out-of-the-box and avoids structural modifications of classes
that would be visible through reflection and could break the instrumented code.
The supported platform is Linux with installed Java and GCC.
link: http://forge.ow2.org/projects/disl/
To compile DiSL please run the "ant" command in the root directory and "make" in the src-agent-c directory.
If the make is complaining about missing java headers, modify the Makefile.local.tmpl accordingly.
INSTALL
=======
DiSL currently fully supports Linux with installed Java, ant, GCC and make.
To compile DiSL please run the "ant" command in the root directory. If "make" is
complaining about missing java headers, modify the Makefile.local.tmpl
accordingly.
EXAMPLES
========
For the basic instrumentation example, please look in the example directory.
Also the src-test directory contains simple examples of DiSL features.
DOCUMENTATION
=============
Please look at http://disl.projects.ow2.org/xwiki/bin/view/Main/Doc.
USER ERRORS
===========
If you get an java error during instrumentation or running your application,
please look at USERERRORS document describing most common problems.
Exception in thread "main" java.lang.VerifyError: (class: ..., method: ... signature: ... Expecting to find object/array on stack
- error occurs if an instrumentation uses uninitialized object
- how to fix: disable java verifier or fix the instrumentation
java process ends with SEGFAULT
- error occurs if an instrumentation instruments one of the java.lang.* classes
and disturbs the java initialization
- how to fix: change the instrumentation or exclude the class causing the
problem in the exclusion list
......@@ -5,10 +5,11 @@ src.disl=src
src.dynbypass=src-dynbypass
src.dynbypass.act=src-dynbypass-act
src.agent.java=src-agent-java
src.dislre.server=src-re-server
src.dislre.dispatch=src-re-disp
src.agent.c=src-agent-c
src.reserver=src-re-server
src.redispatch=src-re-disp
src.reagent=src-re-agent
src.test=src-test
src.example=example
bin=bin
build=build
......@@ -17,4 +18,4 @@ build.afterbootstrap=build-abs
extendedthread.path=${build}/extendedthread.jar
instr.jar.name=dislinstr.jar
instr.jar.name=disl-instr.jar
......@@ -8,10 +8,6 @@
<pathelement location="${bin}" />
</path>
<path id="bootpath">
<pathelement location="${extendedthread.path}" />
</path>
<!-- it automatically compiles all other necessary stuff :) -->
<target name="compile-tlvinserter">
<mkdir dir="${bin}" />
......@@ -34,7 +30,7 @@
<mkdir dir="${bin}" />
<javac srcdir="${src.dynbypass}" destdir="${bin}" debug="true" includeAntRuntime="false">
<classpath refid="buildpath" />
<compilerarg value="-Xbootclasspath/p:${toString:bootpath}" />
<compilerarg value="-Xbootclasspath/p:${extendedthread.path}" />
</javac>
<delete file="${extendedthread.path}" />
</target>
......@@ -51,34 +47,43 @@
</javac>
</target>
<target name="compile-dislre-server">
<javac srcdir="${src.dislre.server}" destdir="${bin}" debug="true" includeAntRuntime="false">
<target name="compile-agent-c">
<exec executable="make" dir="${src.agent.c}" />
</target>
<target name="compile-reserver">
<javac srcdir="${src.reserver}" destdir="${bin}" debug="true" includeAntRuntime="false">
<classpath refid="buildpath" />
</javac>
</target>
<target name="compile-dislre-dispatch">
<javac srcdir="${src.dislre.dispatch}" destdir="${bin}" debug="true" includeAntRuntime="false">
<target name="compile-redispatch">
<javac srcdir="${src.redispatch}" destdir="${bin}" debug="true" includeAntRuntime="false">
<classpath refid="buildpath" />
</javac>
</target>
<target name="compile-test" depends="compile-disl,compile-dislre-server,compile-dislre-dispatch">
<target name="compile-reagent">
<exec executable="make" dir="${src.reagent}" />
</target>
<target name="compile-test" depends="compile-disl,compile-reserver,compile-redispatch">
<javac srcdir="${src.test}" destdir="bin" debug="true" includeAntRuntime="false">
<classpath refid="buildpath" />
</javac>
</target>
<target name="compile" depends="compile-disl,compile-agent-java,compile-test,compile-dislre-server,compile-dislre-dispatch" />
<target name="compile" depends="compile-disl,compile-agent-java,compile-agent-c,compile-test,compile-reserver,compile-redispatch" />
<target name="package-dislserver" depends="compile-disl">
<jar basedir="${bin}" destfile="${build}/dislserver-${disl.version}.jar"
<jar basedir="${bin}" destfile="${build}/disl-server.jar"
includes="ch/usi/dag/disl/**,ch/usi/dag/dislserver/**"
excludes="ch/usi/dag/disl/test/**,ch/usi/dag/disl/testtools/**">
<manifest>
<attribute name="Class-Path" value="${asm.lib} ${instr.jar.name}" />
<attribute name="Class-Path" value="${asm.lib}" />
<attribute name="Main-Class" value="ch.usi.dag.dislserver.DiSLServer" />
<attribute name="DiSL-Version" value="${disl.version}" />
</manifest>
</jar>
</target>
......@@ -96,13 +101,13 @@
<move file="${build.afterbootstrap}/ch/usi/dag/disl/dynamicbypass/DynamicBypassCheck.class"
tofile="${build.afterbootstrap}/DynamicBypassCheck-AfterBootstrap.class" />
<jar basedir="${bin}" destfile="${build}/dislagent-${disl.version}.jar"
<jar basedir="${bin}" destfile="${build}/disl-agent.jar"
includes="ch/usi/dag/dislagent/**,ch/usi/dag/disl/dynamicbypass/**">
<manifest>
<attribute name="Class-Path" value="${instr.jar.name}" />
<attribute name="Premain-Class" value="ch.usi.dag.dislagent.DiSLAgent" />
<attribute name="Can-Redefine-Classes" value="true" />
<attribute name="DiSL-Version" value="${disl.version}" />
</manifest>
<!-- include after bootstrap class -->
......@@ -113,24 +118,24 @@
<delete dir="${build.afterbootstrap}" />
</target>
<target name="package-dislre-server" depends="compile-dislre-server">
<jar basedir="${bin}" destfile="${build}/dislre-server-${disl.version}.jar"
<target name="package-reserver" depends="compile-reserver">
<jar basedir="${bin}" destfile="${build}/dislre-server.jar"
includes="ch/usi/dag/dislreserver/**">
<manifest>
<attribute name="Class-Path" value="${asm.lib} ${instr.jar.name}" />
<attribute name="Class-Path" value="${asm.lib}" />
<attribute name="Main-Class" value="ch.usi.dag.dislreserver.DiSLREServer" />
<attribute name="DiSL-Version" value="${disl.version}" />
</manifest>
</jar>
</target>
<target name="package-dislre-dispatch" depends="compile-dislre-dispatch">
<jar basedir="${bin}" destfile="${build}/dislre-dispatch-${disl.version}.jar"
<target name="package-redispatch" depends="compile-redispatch">
<jar basedir="${bin}" destfile="${build}/dislre-dispatch.jar"
includes="ch/usi/dag/dislre/**">
</jar>
</target>
<target name="package" depends="package-dislserver,package-dislagent-java,package-dislre-server,package-dislre-dispatch" />
<target name="package" depends="package-dislserver,package-dislagent-java,package-reserver,package-redispatch,compile-agent-c,compile-reagent" />
<target name="eclipse-agent" description="creates simple agent jar file for eclipse">
<mkdir dir="build" />
......@@ -161,6 +166,14 @@
<delete dir="${build}" />
<delete dir="${build.thread}" />
<delete dir="${build.afterbootstrap}" />
<exec executable="make" dir="${src.agent.c}">
<arg value="clean" />
</exec>
<exec executable="make" dir="${src.reagent}">
<arg value="clean" />
</exec>
</target>
<!-- *** test instrumentaion package *** -->
......
DiSL SETUP EXAMPLE
==================
This simple example illustrates a basic instrumentation setup. It shows, how
the instrumentation should be packaged and contains a scripts that should ease
running DiSL together with your program.
The example contains simple user application that prints hello string on
command line and instrumentation printing strings before and after application
main.
HOW TO RUN THE EXAMPLE
======================
First be sure that you compiled DiSL (see README in the root directory). Then
follow the steps:
1) compile application calling "ant" in the app directory
2) compile instrumentation calling "ant" in the instrumentation directory
3) run "runApp.sh ./runApp.sh instr/build/disl-instr.jar -jar app/build/example-app.jar"
The last command starts the application together with DiSL. The output of the
application and the applied instrumentation should be visible on command line.
NOTE: If you want to use "runApp.sh" to run your application, don't forget to set
"DISL_LIB_P" variable correctly. Also, you can modify DiSL setting in "runServer.sh".
DIRECTORIES (FILES)
===================
app - contains sources of simple application
instr - contains sources of simple instrumentation
runApp.sh - bash script starting the application together with
DiSL (+ instrumentation)
runServer.sh - starts instrumentation server
runClient.sh - starts application vm with necessary agents
<project name="example-app" default="package" basedir=".">
<path id="buildpath">
<pathelement location="${bin}" />
</path>
<target name="compile">
<mkdir dir="bin" />
<javac srcdir="src" destdir="bin" debug="true" includeAntRuntime="false">
<classpath refid="buildpath" />
</javac>
</target>
<target name="package" depends="compile">
<mkdir dir="build" />
<jar basedir="bin" destfile="build/example-app.jar">
<manifest>
<attribute name="Main-Class" value="Main" />
</manifest>
</jar>
</target>
<target name="clean">
<delete dir="bin" />
<delete dir="build" />
</target>
</project>
public class Main {
public static void main(String[] args) {
System.out.println("Hi -- this is application main");
}
}
lib.path=../../build
dislserver.path=${lib.path}/disl-server.jar
asm.lib=asm-debug-all-4.0.jar
asm.path=${lib.path}/${asm.lib}
instr.jar.name=disl-instr.jar
<project name="example-disl" default="package" basedir=".">
<property file="build.properties" />
<path id="buildpath">
<pathelement location="${asm.path}" />
<pathelement location="${dislserver.path}" />
<pathelement location="${bin}" />
</path>
<target name="compile">
<mkdir dir="bin" />
<javac srcdir="src" destdir="bin" debug="true" includeAntRuntime="false">
<classpath refid="buildpath" />
</javac>
</target>
<target name="package" depends="compile" description="create instrumentation package">
<mkdir dir="build"/>
<jar jarfile="build/${instr.jar.name}"
basedir="bin"
excludes="MANIFEST.MF"
manifest="src/MANIFEST.MF">
</jar>
</target>
<target name="clean">
<delete dir="bin" />
<delete dir="build" />
</target>
</project>
import ch.usi.dag.disl.annotation.After;
import ch.usi.dag.disl.annotation.AfterReturning;
import ch.usi.dag.disl.annotation.Before;
import ch.usi.dag.disl.marker.BodyMarker;
public class DiSLClass {
@Before(marker = BodyMarker.class, scope = "Main.main")
public static void beforemain() {
System.out.println("Before main()");
}
@After(marker = BodyMarker.class, scope = "Main.main")
public static void aftermain() {
System.out.println("After main()");
}
}
Manifest-Version: 1.0
DiSL-Classes: DiSLClass
\ No newline at end of file
# /bin/sh
# default DiSL lib path
if [ -z "${DISL_LIB_P}" ]; then
DISL_LIB_P=../build
fi
# test number of arguments
EXPECTED_ARGS=2
if [ $# -lt $EXPECTED_ARGS ]
then
echo "Usage: `basename $0` instr-lib java-params"
exit
fi
# set server file
SERVER_FILE=.server.pid
export SERVER_FILE
# kill running server
if [ -e ${SERVER_FILE} ]
then
kill -KILL `cat ${SERVER_FILE}`
rm .server.pid
fi
export DISL_LIB_P
# start server (with instrumentation library) and take pid
./runServer.sh $1
# wait for server startup
sleep 3
# run client
./runClient.sh $*
# wait for server shutdown
sleep 1
# kill server
kill -KILL `cat ${SERVER_FILE}` 2> /dev/null
rm .server.pid
#!/bin/bash
# set default lib path
if [ -z "${DISL_LIB_P}" ]; then
DISL_LIB_P=./build
fi
# test number of arguments
EXPECTED_ARGS=2
if [ $# -lt $EXPECTED_ARGS ]
then
echo "Usage: `basename $0` instr-lib java-params"
exit
fi
# set proper lib depending on OS
OS=`uname`
if [ "${OS}" = "Darwin" ]; then
C_AGENT="${DISL_LIB_P}/libdislagent.jnilib"
else
C_AGENT="${DISL_LIB_P}/libdislagent.so"
fi
# get instrumentation library and shift parameters
INSTR_LIB=$1
shift
# start client
java -agentpath:${C_AGENT} \
-javaagent:${DISL_LIB_P}/disl-agent.jar \
-Xbootclasspath/a:${DISL_LIB_P}/disl-agent.jar:${INSTR_LIB} \
$*
#!/bin/sh
# set default lib path
if [ -z "${DISL_LIB_P}" ]; then
DISL_LIB_P=./build
fi
# available options
# -Ddebug=true \
# -Ddisl.classes="list of disl classes (: - separator)"
# -Ddisl.noexcepthandler=true \
# -Ddisl.exclusionList="path" \
# -Ddislserver.instrumented="path" \
# -Ddislserver.uninstrumented="path" \
# -Ddislserver.port="portNum" \
# -Ddislserver.timestat=true \
# -Ddislserver.continuous=true \
# get instrumentation library and shift parameters
INSTR_LIB=$1
shift
# start server
java $* \
-cp ${INSTR_LIB}:${DISL_LIB_P}/disl-server.jar \
ch.usi.dag.dislserver.DiSLServer \
&
# print pid to the server file
if [ -n "${SERVER_FILE}" ]; then
echo $! > ${SERVER_FILE}
fi
#!/bin/bash
BASE_DIR="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# set default lib path
if [ -z "${DISL_LIB_P}" ]; then
DISL_LIB_P=./build
fi
OS=`uname`
# test number of arguments
EXPECTED_ARGS=2
if [ $# -lt $EXPECTED_ARGS ]
then
echo "Usage: `basename $0` instr-lib java-params"
exit
fi
# set proper lib depending on OS
OS=`uname`
if [ "${OS}" = "Darwin" ]; then
C_AGENT="${BASE_DIR}/src-agent-c/libdislagent.jnilib"
RE_AGENT="${BASE_DIR}/src-re-agent/libdislreagent.jnilib"
C_AGENT="${DISL_LIB_P}/libdislagent.jnilib"
RE_AGENT="${DISL_LIB_P}/libdislreagent.jnilib"
else
C_AGENT="${BASE_DIR}/src-agent-c/libdislagent.so"
RE_AGENT="${BASE_DIR}/src-re-agent/libdislreagent.so"
C_AGENT="${DISL_LIB_P}/libdislagent.so"
RE_AGENT="${DISL_LIB_P}/libdislreagent.so"
fi
# get instrumentation library and shift parameters
INSTR_LIB=$1
shift
# start client
java -agentpath:${C_AGENT} \
-agentpath:${RE_AGENT} \
-javaagent:${BASE_DIR}/build/dislagent-unspec.jar \
-Xbootclasspath/a:${BASE_DIR}/build/dislagent-unspec.jar:${BASE_DIR}/build/dislinstr.jar:${BASE_DIR}/build/dislre-dispatch-unspec.jar \
-cp ${BASE_DIR}/bin/ \
-javaagent:${DISL_LIB_P}/disl-agent.jar \
-Xbootclasspath/a:${DISL_LIB_P}/disl-agent.jar:${INSTR_LIB}:${DISL_LIB_P}/dislre-dispatch.jar \
$*
#!/bin/bash
#!/bin/sh
BASE_DIR="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# set default lib path
if [ -z "${DISL_LIB_P}" ]; then
DISL_LIB_P=./build
fi
# available options
# -Ddebug=true \
# -Ddislreserver.port="portNum" \
# get instrumentation library and shift parameters
INSTR_LIB=$1
shift
# start server
java $* \
-jar ${BASE_DIR}/build/dislre-server-unspec.jar \
-cp ${INSTR_LIB}:${DISL_LIB_P}/dislre-server.jar \
ch.usi.dag.dislreserver.DiSLREServer \
&
echo $! > ${RE_SERVER_FILE}
# print pid to the server file
if [ -n "${RE_SERVER_FILE}" ]; then
echo $! > ${RE_SERVER_FILE}
fi
#!/bin/bash
#!/bin/sh
BASE_DIR="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# set default lib path
if [ -z "${DISL_LIB_P}" ]; then
DISL_LIB_P=./build
fi
# available options
# -Ddebug=true \
......@@ -13,9 +16,17 @@ BASE_DIR="$( cd -P "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# -Ddislserver.timestat=true \
# -Ddislserver.continuous=true \
# get instrumentation library and shift parameters
INSTR_LIB=$1
shift
# start server
java $* \
-jar ${BASE_DIR}/build/dislserver-unspec.jar \
-cp ${INSTR_LIB}:${DISL_LIB_P}/disl-server.jar \
ch.usi.dag.dislserver.DiSLServer \
&
echo $! > ${SERVER_FILE}
# print pid to the server file
if [ -n "${SERVER_FILE}" ]; then
echo $! > ${SERVER_FILE}
fi
......@@ -8,7 +8,7 @@ then
exit
fi
SERVER_FILE=server.pid
SERVER_FILE=.server.pid
export SERVER_FILE
RE_SERVER_FILE=re_server.pid
......@@ -18,29 +18,42 @@ export RE_SERVER_FILE
if [ -e ${SERVER_FILE} ]
then
kill -KILL `cat ${SERVER_FILE}`
rm ${SERVER_FILE}
rm .server.pid
fi
# kill running server
if [ -e ${RE_SERVER_FILE} ]
then
kill -KILL `cat ${RE_SERVER_FILE}`
rm ${RE_SERVER_FILE}
fi
# represents the observed program
TARGET_CLASS="ch.usi.dag.disl.test.$1.TargetClass"
# start server and take pid
# suppress output
# compile the test package - suppress output
ant package-test -Dtest.name=$1 > /dev/null
./runServer.sh
./runREServer.sh
INSTR_LIB=build/disl-instr.jar
# start server and take pid
./runServer.sh ${INSTR_LIB}
# start reserver and take pid
./runREServer.sh ${INSTR_LIB}
# wait for server startup
sleep 3
# run client
./runClient.sh ${TARGET_CLASS}
./runClient.sh ${INSTR_LIB} -cp bin/ ${TARGET_CLASS}
# wait for server shutdown
sleep 1
# kill servers
# kill server
kill -KILL `cat ${SERVER_FILE}` 2> /dev/null
rm ${SERVER_FILE}
rm .server.pid
kill -KILL `cat ${RE_SERVER_FILE}` 2> /dev/null
rm ${RE_SERVER_FILE}
......@@ -3,6 +3,8 @@ ifneq (, $(wildcard Makefile.local))
include Makefile.local
endif
BUILDDIR=../build
# Source lists
LIBNAME=dislagent
SOURCES=dislagent.c
......@@ -36,7 +38,8 @@ ifeq ($(DEBUG), TRUE)
CFLAGS += -DDEBUG
endif
all: $(LIBRARY)
build: $(LIBRARY)
cp $(LIBRARY) $(BUILDDIR)
# Build native library
$(LIBRARY): $(OBJECTS)
......@@ -48,3 +51,5 @@ clean:
debug:
$(MAKE) DEBUG=TRUE
all: build
\ No newline at end of file
......@@ -3,6 +3,8 @@ ifneq (, $(wildcard Makefile.local))
include Makefile.local
endif
BUILDDIR=../build
# Source lists
LIBNAME=dislreagent
SOURCES=dislreagent.c
......@@ -31,7 +33,8 @@ CFLAGS += $(COMMON_FLAGS)
CFLAGS += -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/linux
all: $(LIBRARY)
build: $(LIBRARY)
cp $(LIBRARY) $(BUILDDIR)
# Build native library
$(LIBRARY): $(OBJECTS)
......@@ -40,3 +43,5 @@ $(LIBRARY): $(OBJECTS)
# Cleanup the built bits
clean:
rm -f $(LIBRARY) $(OBJECTS)
all: build
\ No newline at end of file
......@@ -459,9 +459,13 @@ public class DiSL {
* Instruments array of bytes representing a class
*
* @param classAsBytes class as array of bytes
* @return instrumeted class as array of bytes
* @return instrumented class as array of bytes
*/
public byte[] instrument(byte[] classAsBytes) throws DiSLException {
// TODO ! current static context interface does not allow to have nice
// synchronization - it should be redesigned such as the staticContextData
// also invokes the required method and returns result - if this method
// (and static context class itself) will be synchronized, it should work
public synchronized byte[] instrument(byte[] classAsBytes) throws DiSLException {
// output bytes into the file
try {
......
......@@ -2,6 +2,8 @@ package ch.usi.dag.disl.guardcontext;
/**
* Guard context is used to invoke guard inside of other guard.
*
* Guard implementation has to thread-safe.
*/
public interface GuardContext {
......
......@@ -6,9 +6,12 @@ import java.util.Map;
import ch.usi.dag.disl.exception.GuardException;
/**
* Note that all methods accessing and working with singleton has to be
* thread-safe.
*/
public class GuardResolver {
private static GuardResolver instance = null;
// Guard to guard method map
......
package ch.usi.dag.disl.scope;
/**
* Interface for matching snippet scope
* Interface for matching snippet scope.
*
* Scope implementation has to thread-safe.
*/
public interface Scope {
......
......@@ -8,6 +8,8 @@ import ch.usi.dag.disl.snippet.Shadow;
* All static context methods should follow convention:
* a) static context methods does not have parameters
* b) return value can be only basic type or String
*
* StaticContext implementation has to thread-safe.
*/
public interface StaticContext {
......
......@@ -19,7 +19,7 @@ import ch.usi.dag.disl.util.Constants;
public class SCGenerator {
class